]> source.dussan.org Git - sonarqube.git/commitdiff
Use protocol buffers format for analysis reports
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 26 Jan 2015 17:24:01 +0000 (18:24 +0100)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 2 Feb 2015 16:27:19 +0000 (17:27 +0100)
49 files changed:
pom.xml
server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportService.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/ComputationComponents.java
server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContext.java
server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java
server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueComputation.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/DigestReportStep.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportServiceTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/computation/ComputationThreadLauncherTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/issue/IssueComputationTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/DigestReportStepTest.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexComponentsStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/PurgeDatastoresStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/SwitchSnapshotStepTest.java
sonar-batch-protocol/compile_protobuf.sh [new file with mode: 0644]
sonar-batch-protocol/pom.xml
sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/Constants.java [new file with mode: 0644]
sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchOutput.java [new file with mode: 0644]
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/ProtobufUtil.java [new file with mode: 0644]
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchOutputReader.java [new file with mode: 0644]
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchOutputWriter.java [new file with mode: 0644]
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java [new file with mode: 0644]
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/ReportHelper.java [deleted file]
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/component/ReportComponent.java [deleted file]
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/component/ReportComponents.java [deleted file]
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/component/package-info.java [deleted file]
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/issue/ReportIssue.java [deleted file]
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/issue/package-info.java [deleted file]
sonar-batch-protocol/src/main/protobuf/batch_output.proto [new file with mode: 0644]
sonar-batch-protocol/src/main/protobuf/constants.proto [new file with mode: 0644]
sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/ProtobufUtilTest.java [new file with mode: 0644]
sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchOutputReaderTest.java [new file with mode: 0644]
sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchOutputWriterTest.java [new file with mode: 0644]
sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/FileStructureTest.java [new file with mode: 0644]
sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/ReportHelperTest.java [deleted file]
sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/component/ReportComponentsTest.java [deleted file]
sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/issue/ReportIssueTest.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/index/BatchResource.java
sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java
sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java
sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java
sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java
sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java
sonar-batch/src/test/resources/org/sonar/batch/report/ComponentsPublisherTest/expected.json [deleted file]
sonar-batch/src/test/resources/org/sonar/batch/report/ComponentsPublisherTest/testComponentPublisher_containing_file_without_language.json [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/utils/ZipUtilsTest.java

diff --git a/pom.xml b/pom.xml
index 67787434c992f6f24625e634dfca6072fe17c979..ee6a3b39404703f9a4c2d413c76cb9427a5c0fe0 100644 (file)
--- a/pom.xml
+++ b/pom.xml
         <artifactId>freemarker</artifactId>
         <version>2.3.20</version>
       </dependency>
+      <dependency>
+        <groupId>com.google.protobuf</groupId>
+        <artifactId>protobuf-java</artifactId>
+        <version>2.6.1</version>
+      </dependency>
 
       <!-- tomcat -->
       <dependency>
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportService.java b/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportService.java
deleted file mode 100644 (file)
index 29fc093..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.computation;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.collect.Iterables;
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.issue.internal.FieldDiffs;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.utils.Duration;
-import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.batch.protocol.output.ReportHelper;
-import org.sonar.batch.protocol.output.component.ReportComponent;
-import org.sonar.batch.protocol.output.component.ReportComponents;
-import org.sonar.batch.protocol.output.issue.ReportIssue;
-import org.sonar.server.computation.issue.IssueComputation;
-
-import javax.annotation.Nullable;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Date;
-
-public class AnalysisReportService {
-
-  private final IssueComputation issueComputation;
-
-  public AnalysisReportService(IssueComputation issueComputation) {
-    this.issueComputation = issueComputation;
-  }
-
-  public void digest(ComputationContext context) {
-    initComponents(context);
-    parseReport(context);
-  }
-
-  @VisibleForTesting
-  void initComponents(ComputationContext context) {
-    File file = new File(context.getReportDirectory(), "components.json");
-
-    try (InputStream resourcesStream = new FileInputStream(file)) {
-      String json = IOUtils.toString(resourcesStream);
-      ReportComponents reportComponents = ReportComponents.fromJson(json);
-      context.addResources(reportComponents);
-    } catch (IOException e) {
-      throw new IllegalStateException("Failed to read issues", e);
-    }
-  }
-
-  private void parseReport(ComputationContext context) {
-    ReportHelper helper = ReportHelper.create(context.getReportDirectory());
-    ReportComponent root = helper.getComponents().root();
-    browseComponent(context, helper, root);
-    issueComputation.afterReportProcessing();
-  }
-
-  private void browseComponent(ComputationContext context, ReportHelper helper, ReportComponent component) {
-    Iterable<ReportIssue> reportIssues = helper.getIssues(component.batchId());
-    browseComponentIssues(context, component, reportIssues);
-    for (ReportComponent child : component.children()) {
-      browseComponent(context, helper, child);
-    }
-  }
-
-  private void browseComponentIssues(final ComputationContext context, ReportComponent component, Iterable<ReportIssue> reportIssues) {
-    issueComputation.processComponentIssues(component.uuid(), Iterables.transform(reportIssues, new Function<ReportIssue, DefaultIssue>() {
-      @Override
-      public DefaultIssue apply(ReportIssue input) {
-        return toIssue(context, input);
-      }
-    }));
-  }
-
-  private DefaultIssue toIssue(ComputationContext context, ReportIssue issue) {
-    DefaultIssue defaultIssue = new DefaultIssue();
-    defaultIssue.setKey(issue.key());
-    ReportComponent component = context.getComponentByBatchId(issue.componentBatchId());
-    setComponent(defaultIssue, component);
-    defaultIssue.setRuleKey(RuleKey.of(issue.ruleRepo(), issue.ruleKey()));
-    defaultIssue.setSeverity(issue.severity());
-    defaultIssue.setManualSeverity(issue.isManualSeverity());
-    defaultIssue.setMessage(issue.message());
-    defaultIssue.setLine(issue.line());
-    defaultIssue.setProjectUuid(context.getProject().uuid());
-    defaultIssue.setProjectKey(context.getProject().key());
-    defaultIssue.setEffortToFix(issue.effortToFix());
-    setDebt(defaultIssue, issue.debt());
-    setFieldDiffs(defaultIssue, issue.diffFields(), context.getAnalysisDate());
-    defaultIssue.setStatus(issue.status());
-    defaultIssue.setTags(issue.tags());
-    defaultIssue.setResolution(issue.resolution());
-    defaultIssue.setReporter(issue.reporter());
-    defaultIssue.setAssignee(issue.assignee());
-    defaultIssue.setChecksum(issue.checksum());
-    defaultIssue.setAttributes(KeyValueFormat.parse(issue.issueAttributes()));
-    defaultIssue.setAuthorLogin(issue.authorLogin());
-    defaultIssue.setActionPlanKey(issue.actionPlanKey());
-    defaultIssue.setCreationDate(issue.creationDate());
-    defaultIssue.setUpdateDate(issue.updateDate());
-    defaultIssue.setCloseDate(issue.closeDate());
-    defaultIssue.setChanged(issue.isChanged());
-    defaultIssue.setNew(issue.isNew());
-    defaultIssue.setSelectedAt(issue.selectedAt());
-    defaultIssue.setSendNotifications(issue.mustSendNotifications());
-    return defaultIssue;
-  }
-
-  private DefaultIssue setFieldDiffs(DefaultIssue issue, String diffFields, Date analysisDate) {
-    FieldDiffs fieldDiffs = FieldDiffs.parse(diffFields);
-    fieldDiffs.setCreationDate(analysisDate);
-    issue.setCurrentChange(fieldDiffs);
-
-    return issue;
-  }
-
-  private DefaultIssue setComponent(DefaultIssue issue, @Nullable ReportComponent component) {
-    if (component != null) {
-      issue.setComponentUuid(component.uuid());
-    }
-    return issue;
-  }
-
-  private DefaultIssue setDebt(DefaultIssue issue, @Nullable Long debt) {
-    if (debt != null) {
-      issue.setDebt(Duration.create(debt));
-    }
-
-    return issue;
-  }
-}
index 7a202030b186042809aa6a731161ae7b1611e8ea..a26e06d99d47f595124a01d5f02e18ead41e7022 100644 (file)
@@ -41,7 +41,6 @@ public class ComputationComponents {
     return Arrays.asList(
       ComputationService.class,
       ComputationSteps.class,
-      AnalysisReportService.class,
 
       // issues
       ScmAccountCacheLoader.class,
index cbe8fc4f73616918ed223accb27c942080f8325a..aae1beeb13c7e6911584f19dbb38ba0c75e0aead 100644 (file)
 
 package org.sonar.server.computation;
 
-import com.google.common.annotations.VisibleForTesting;
-import org.sonar.batch.protocol.output.component.ReportComponent;
-import org.sonar.batch.protocol.output.component.ReportComponents;
+import org.sonar.batch.protocol.output.BatchOutputReader;
 import org.sonar.core.component.ComponentDto;
 import org.sonar.core.computation.db.AnalysisReportDto;
 
-import javax.annotation.CheckForNull;
-
-import java.io.File;
 import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
 
 public class ComputationContext {
 
   private final AnalysisReportDto reportDto;
   private final ComponentDto project;
-  private final File reportDirectory;
-  private Map<Long, ReportComponent> components = new HashMap<>();
-  private Date analysisDate;
+  private final BatchOutputReader reportReader;
+
+  /**
+   * Cache of analysis date as it can be accessed several times
+   */
+  private Date analysisDate = null;
 
-  public ComputationContext(AnalysisReportDto reportDto, ComponentDto project, File reportDir) {
+  public ComputationContext(AnalysisReportDto reportDto, ComponentDto project, BatchOutputReader reportReader) {
     this.reportDto = reportDto;
     this.project = project;
-    this.reportDirectory = reportDir;
+    this.reportReader = reportReader;
   }
 
   public AnalysisReportDto getReportDto() {
@@ -55,35 +51,14 @@ public class ComputationContext {
     return project;
   }
 
-  public File getReportDirectory() {
-    return reportDirectory;
-  }
-
-  public void addResources(ReportComponents reportComponents) {
-    analysisDate = reportComponents.analysisDate();
-    addResource(reportComponents.root());
+  public BatchOutputReader getReportReader() {
+    return reportReader;
   }
 
-  @CheckForNull
-  public ReportComponent getComponentByBatchId(Long batchId) {
-    return components.get(batchId);
-  }
-
-  @VisibleForTesting
-  Map<Long, ReportComponent> getComponents() {
-    return components;
-  }
-
-  private void addResource(ReportComponent resource) {
-    this.components.put(resource.batchId(), resource);
-    for (ReportComponent childResource : resource.children()) {
-      addResource(childResource);
-    }
-  }
-
-  @CheckForNull
   public Date getAnalysisDate() {
+    if (analysisDate == null) {
+      analysisDate = new Date(reportReader.readMetadata().getAnalysisDate());
+    }
     return analysisDate;
   }
-
 }
index dc798c81e2b9197632c025c7194334e06ede8ebf..4b127c9d5dfca85754c352870cb0405e5426eb08 100644 (file)
@@ -28,6 +28,7 @@ import org.sonar.api.ServerComponent;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.TempFolder;
 import org.sonar.api.utils.TimeProfiler;
+import org.sonar.batch.protocol.output.BatchOutputReader;
 import org.sonar.core.activity.Activity;
 import org.sonar.core.component.ComponentDto;
 import org.sonar.core.computation.db.AnalysisReportDto;
@@ -64,8 +65,8 @@ public class ComputationService implements ServerComponent {
     ComponentDto project = loadProject(report);
     File reportDir = tempFolder.newDir();
     try {
-      ComputationContext context = new ComputationContext(report, project, reportDir);
       decompressReport(report, reportDir);
+      ComputationContext context = new ComputationContext(report, project, new BatchOutputReader(reportDir));
       for (ComputationStep step : steps.orderedSteps()) {
         TimeProfiler stepProfiler = new TimeProfiler(LOG).start(step.getDescription());
         step.execute(context);
@@ -112,7 +113,7 @@ public class ComputationService implements ServerComponent {
     } finally {
       MyBatis.closeQuietly(session);
     }
-    long stoptTime = System.currentTimeMillis();
-    LOG.info("Analysis report loaded and uncompressed in " + (stoptTime-startTime) + "ms (project=" + report.getProjectKey() +")");
+    long stopTime = System.currentTimeMillis();
+    LOG.info("Analysis report loaded and uncompressed in " + (stopTime - startTime) + "ms (project=" + report.getProjectKey() + ")");
   }
 }
index fdf1e48deb8338cdd071a4abb968f4cb7bf31640..1717b91fd19c63c7f77569765e83e060a6dec261 100644 (file)
@@ -21,40 +21,86 @@ package org.sonar.server.computation.issue;
 
 import com.google.common.collect.Sets;
 import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.issue.internal.FieldDiffs;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.Duration;
+import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.batch.protocol.output.BatchOutput;
 import org.sonar.core.rule.RuleDto;
+import org.sonar.server.computation.ComputationContext;
 import org.sonar.server.util.cache.DiskCache;
 
+import java.util.Date;
+
 public class IssueComputation {
 
   private final RuleCache ruleCache;
   private final ScmAccountCache scmAccountCache;
   private final SourceLinesCache linesCache;
-  private final DiskCache<DefaultIssue>.DiskAppender finalIssuesAppender;
+  private final DiskCache<DefaultIssue>.DiskAppender diskIssuesAppender;
 
   public IssueComputation(RuleCache ruleCache, SourceLinesCache linesCache, ScmAccountCache scmAccountCache,
-                          IssueCache issueCache) {
+    IssueCache issueCache) {
     this.ruleCache = ruleCache;
     this.linesCache = linesCache;
     this.scmAccountCache = scmAccountCache;
-    this.finalIssuesAppender = issueCache.newAppender();
+    this.diskIssuesAppender = issueCache.newAppender();
   }
 
-  public void processComponentIssues(String componentUuid, Iterable<DefaultIssue> issues) {
+  public void processComponentIssues(ComputationContext context, String componentUuid, Iterable<BatchOutput.ReportIssue> issues) {
     linesCache.init(componentUuid);
-    for (DefaultIssue issue : issues) {
+    for (BatchOutput.ReportIssue reportIssue : issues) {
+      DefaultIssue issue = toDefaultIssue(context, componentUuid, reportIssue);
       if (issue.isNew()) {
         guessAuthor(issue);
         autoAssign(issue);
         copyRuleTags(issue);
         // TODO execute extension points
       }
-      finalIssuesAppender.append(issue);
+      diskIssuesAppender.append(issue);
     }
     linesCache.clear();
   }
 
+  private DefaultIssue toDefaultIssue(ComputationContext context, String componentUuid, BatchOutput.ReportIssue issue) {
+    DefaultIssue target = new DefaultIssue();
+    target.setKey(issue.getUuid());
+    target.setComponentUuid(componentUuid);
+    target.setRuleKey(RuleKey.of(issue.getRuleRepository(), issue.getRuleKey()));
+    target.setSeverity(issue.getSeverity().name());
+    target.setManualSeverity(issue.getManualSeverity());
+    target.setMessage(issue.hasMsg() ? issue.getMsg() : null);
+    target.setLine(issue.hasLine() ? issue.getLine() : null);
+    target.setProjectUuid(context.getProject().uuid());
+    target.setProjectKey(context.getProject().key());
+    target.setEffortToFix(issue.hasEffortToFix() ? issue.getEffortToFix() : null);
+    target.setDebt(issue.hasDebtInMinutes() ? Duration.create(issue.getDebtInMinutes()) : null);
+    if (issue.hasDiffFields()) {
+      FieldDiffs fieldDiffs = FieldDiffs.parse(issue.getDiffFields());
+      fieldDiffs.setCreationDate(context.getAnalysisDate());
+      target.setCurrentChange(fieldDiffs);
+    }
+    target.setStatus(issue.getStatus());
+    target.setTags(issue.getTagsList());
+    target.setResolution(issue.hasResolution() ? issue.getResolution() : null);
+    target.setReporter(issue.hasReporter() ? issue.getReporter() : null);
+    target.setAssignee(issue.hasAssignee() ? issue.getAssignee() : null);
+    target.setChecksum(issue.hasChecksum() ? issue.getChecksum() : null);
+    target.setAttributes(issue.hasAttributes() ? KeyValueFormat.parse(issue.getAttributes()) : null);
+    target.setAuthorLogin(issue.hasAuthorLogin() ? issue.getAuthorLogin() : null);
+    target.setActionPlanKey(issue.hasActionPlanKey() ? issue.getActionPlanKey() : null);
+    target.setCreationDate(issue.hasCreationDate() ? new Date(issue.getCreationDate()) : null);
+    target.setUpdateDate(issue.hasUpdateDate() ? new Date(issue.getUpdateDate()) : null);
+    target.setCloseDate(issue.hasCloseDate() ? new Date(issue.getCloseDate()) : null);
+    target.setChanged(issue.getIsChanged());
+    target.setNew(issue.getIsNew());
+    target.setSelectedAt(issue.hasSelectedAt() ? issue.getSelectedAt() : null);
+    target.setSendNotifications(issue.getMustSendNotification());
+    return target;
+  }
+
   public void afterReportProcessing() {
-    finalIssuesAppender.close();
+    diskIssuesAppender.close();
   }
 
   private void guessAuthor(DefaultIssue issue) {
index e19da64b18f9e1eedad59762f9c522bf0d6d6758..d73706b7060953f2dd911443c3cb7482fb4df511 100644 (file)
@@ -34,7 +34,7 @@ public class ComputationSteps {
    */
   public static List<Class<? extends ComputationStep>> orderedStepClasses() {
     return Arrays.asList(
-      DigestReportStep.class,
+      ParseReportStep.class,
       PersistIssuesStep.class,
       SwitchSnapshotStep.class,
       IndexComponentsStep.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/DigestReportStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/DigestReportStep.java
deleted file mode 100644 (file)
index 8c0b801..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.computation.step;
-
-import org.sonar.server.computation.AnalysisReportService;
-import org.sonar.server.computation.ComputationContext;
-
-public class DigestReportStep implements ComputationStep {
-
-  private final AnalysisReportService reportService;
-
-  public DigestReportStep(AnalysisReportService reportService) {
-    this.reportService = reportService;
-  }
-
-  @Override
-  public void execute(ComputationContext context) {
-    reportService.digest(context);
-  }
-
-  @Override
-  public String getDescription() {
-    return "Digest analysis report";
-  }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ParseReportStep.java
new file mode 100644 (file)
index 0000000..e83ec7c
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.computation.step;
+
+import org.sonar.batch.protocol.output.BatchOutputReader;
+import org.sonar.batch.protocol.output.BatchOutput;
+import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.computation.issue.IssueComputation;
+
+public class ParseReportStep implements ComputationStep {
+
+  private final IssueComputation issueComputation;
+
+  public ParseReportStep(IssueComputation issueComputation) {
+    this.issueComputation = issueComputation;
+  }
+
+  @Override
+  public void execute(ComputationContext context) {
+    int rootComponentRef = context.getReportReader().readMetadata().getRootComponentRef();
+    processComponent(context, rootComponentRef);
+    issueComputation.afterReportProcessing();
+  }
+
+  private void processComponent(ComputationContext context, int componentRef) {
+    BatchOutputReader reader = context.getReportReader();
+    BatchOutput.ReportComponent component = reader.readComponent(componentRef);
+    issueComputation.processComponentIssues(context, component.getUuid(), reader.readComponentIssues(componentRef));
+
+    for (Integer childRef : component.getChildRefsList()) {
+      processComponent(context, childRef);
+    }
+  }
+
+  @Override
+  public String getDescription() {
+    return "Digest analysis report";
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportServiceTest.java
deleted file mode 100644 (file)
index c9cf48d..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.
- */
-///*
-// * SonarQube, open source software quality management tool.
-// * Copyright (C) 2008-2014 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.computation;
-//
-//import com.google.common.collect.Lists;
-//import org.junit.Before;
-//import org.junit.Ignore;
-//import org.junit.Test;
-//import org.sonar.api.issue.internal.DefaultIssue;
-//import org.sonar.api.rules.RuleFinder;
-//import org.sonar.batch.protocol.output.component.ReportComponent;
-//import org.sonar.core.component.ComponentDto;
-//import org.sonar.core.computation.db.AnalysisReportDto;
-//import org.sonar.core.issue.db.IssueStorage;
-//import org.sonar.core.persistence.DbSession;
-//import org.sonar.core.persistence.MyBatis;
-//
-//import java.io.File;
-//import java.util.List;
-//
-//import static org.assertj.core.api.Assertions.assertThat;
-//import static org.mockito.Matchers.any;
-//import static org.mockito.Mockito.mock;
-//import static org.mockito.Mockito.when;
-//
-//public class AnalysisReportServiceTest {
-//  private AnalysisReportService sut;
-//
-//  private IssueStorage issueStorage;
-//
-//  @Before
-//  public void before() throws Exception {
-//    issueStorage = new FakeIssueStorage();
-//    ComputeEngineIssueStorageFactory issueStorageFactory = mock(ComputeEngineIssueStorageFactory.class);
-//    when(issueStorageFactory.newComputeEngineIssueStorage(any(ComponentDto.class))).thenReturn(issueStorage);
-//    sut = new AnalysisReportService(issueStorageFactory);
-//  }
-//
-//  @Test
-//  public void load_resources() throws Exception {
-//    File dir = new File(getClass().getResource("/org/sonar/server/computation/AnalysisReportServiceTest/report-folder").getFile());
-//    ComputationContext context = new ComputationContext(mock(AnalysisReportDto.class), mock(ComponentDto.class), dir);
-//
-//    sut.initComponents(context);
-//
-//    assertThat(context.getComponents()).hasSize(4);
-//  }
-//
-//  @Test
-//  @Ignore("Temporarily ignored")
-//  public void save_issues() throws Exception {
-//    File dir = new File(getClass().getResource("/org/sonar/server/computation/AnalysisReportServiceTest/report-folder").getFile());
-//    ComputationContext context = new FakeComputationContext(dir);
-//
-//    sut.saveIssues(context);
-//
-//    assertThat(((FakeIssueStorage) issueStorage).issues).hasSize(6);
-//  }
-//
-//  private static class FakeIssueStorage extends IssueStorage {
-//
-//    public List<DefaultIssue> issues = null;
-//
-//    protected FakeIssueStorage() {
-//      super(mock(MyBatis.class), mock(RuleFinder.class));
-//    }
-//
-//    @Override
-//    public void save(Iterable<DefaultIssue> issues) {
-//      this.issues = Lists.newArrayList(issues);
-//    }
-//
-//    @Override
-//    protected void doInsert(DbSession batchSession, long now, DefaultIssue issue) {
-//
-//    }
-//
-//    @Override
-//    protected void doUpdate(DbSession batchSession, long now, DefaultIssue issue) {
-//
-//    }
-//  }
-//
-//  private static class FakeComputationContext extends ComputationContext {
-//
-//    public FakeComputationContext(File reportDir) {
-//      super(mock(AnalysisReportDto.class), mock(ComponentDto.class), reportDir);
-//    }
-//
-//    @Override
-//    public ReportComponent getComponentByBatchId(Long batchId) {
-//      return new ReportComponent()
-//        .setBatchId(123)
-//        .setId(456);
-//    }
-//  }
-//
-//}
index 3cf8c22446c4a15bd893f38890e4133ab78593ca..61379a03b03a589efee3950ae6c64acaf46486a4 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-///*
-// * SonarQube, open source software quality management tool.
-// * Copyright (C) 2008-2014 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.computation;
-//
-//import org.junit.After;
-//import org.junit.Before;
-//import org.junit.Rule;
-//import org.junit.Test;
-//import org.junit.rules.DisableOnDebug;
-//import org.junit.rules.TestRule;
-//import org.junit.rules.Timeout;
-//import org.sonar.api.platform.Server;
-//
-//import java.util.concurrent.TimeUnit;
-//
-//import static org.mockito.Mockito.*;
-//
-//public class ComputationThreadLauncherTest {
-//
-//  @Rule
-//  public TestRule timeout = new DisableOnDebug(Timeout.seconds(5));
-//
-//  private ComputationThreadLauncher sut;
-//  private ComputationService service;
-//  private AnalysisReportQueue queue;
-//
-//  @Before
-//  public void before() {
-//    this.service = mock(ComputationService.class);
-//    this.queue = mock(AnalysisReportQueue.class);
-//  }
-//
-//  @After
-//  public void after() {
-//    sut.stop();
-//  }
-//
-//  @Test
-//  public void call_findAndBook_when_launching_a_recurrent_task() throws Exception {
-//    sut = new ComputationThreadLauncher(service, queue, 0, 1, TimeUnit.MILLISECONDS);
-//
-//    sut.onServerStart(mock(Server.class));
-//
-//    sleep();
-//
-//    verify(queue, atLeastOnce()).pop();
-//  }
-//
-//  @Test
-//  public void call_findAndBook_when_executing_task_immediately() throws Exception {
-//    sut = new ComputationThreadLauncher(service, queue, 1, 1, TimeUnit.HOURS);
-//    sut.start();
-//
-//    sut.startAnalysisTaskNow();
-//
-//    sleep();
-//
-//    verify(queue, atLeastOnce()).pop();
-//  }
-//
-//  private void sleep() throws InterruptedException {
-//    TimeUnit.MILLISECONDS.sleep(500L);
-//  }
-//}
+
+package org.sonar.server.computation;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.DisableOnDebug;
+import org.junit.rules.TestRule;
+import org.junit.rules.Timeout;
+import org.sonar.api.platform.Server;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.mockito.Mockito.*;
+
+public class ComputationThreadLauncherTest {
+
+  @Rule
+  public TestRule timeout = new DisableOnDebug(Timeout.seconds(5));
+
+  ComputationThreadLauncher sut;
+  AnalysisReportQueue queue;
+
+  @Before
+  public void before() {
+    this.queue = mock(AnalysisReportQueue.class);
+  }
+
+  @After
+  public void after() {
+    sut.stop();
+  }
+
+  @Test
+  public void call_findAndBook_when_launching_a_recurrent_task() throws Exception {
+    sut = new ComputationThreadLauncher(queue, 0, 1, TimeUnit.MILLISECONDS);
+
+    sut.onServerStart(mock(Server.class));
+
+    sleep();
+
+    verify(queue, atLeastOnce()).pop();
+  }
+
+  @Test
+  public void call_findAndBook_when_executing_task_immediately() throws Exception {
+    sut = new ComputationThreadLauncher(queue, 1, 1, TimeUnit.HOURS);
+    sut.start();
+
+    sut.startAnalysisTaskNow();
+
+    sleep();
+
+    verify(queue, atLeastOnce()).pop();
+  }
+
+  private void sleep() throws InterruptedException {
+    TimeUnit.MILLISECONDS.sleep(500L);
+  }
+}
index 946e0d151cc04ab04fda954de4f63936667b9d75..0e9b3dc8106fcbfdcc543923db6a6fa644fef21a 100644 (file)
@@ -25,18 +25,20 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
+import org.sonar.api.issue.Issue;
 import org.sonar.api.issue.internal.DefaultIssue;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.System2;
+import org.sonar.batch.protocol.output.BatchOutput;
 import org.sonar.core.rule.RuleDto;
+import org.sonar.server.computation.ComputationContext;
 
 import java.io.IOException;
 import java.util.Arrays;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
 
 public class IssueComputationTest {
 
@@ -45,129 +47,133 @@ public class IssueComputationTest {
   @Rule
   public TemporaryFolder temp = new TemporaryFolder();
 
+  IssueComputation sut;
+
   // inputs
   RuleCache ruleCache = mock(RuleCache.class);
   SourceLinesCache lineCache = mock(SourceLinesCache.class);
   ScmAccountCache scmAccountCache = mock(ScmAccountCache.class);
-  DefaultIssue issue = new DefaultIssue().setRuleKey(RULE_KEY).setKey("ISSUE_A");
   RuleDto rule = new RuleDto().setRepositoryKey(RULE_KEY.repository()).setRuleKey(RULE_KEY.rule());
+  BatchOutput.ReportIssue.Builder inputIssue = BatchOutput.ReportIssue.newBuilder()
+    .setUuid("ISSUE_A")
+    .setRuleRepository(RULE_KEY.repository())
+    .setRuleKey(RULE_KEY.rule())
+    .setStatus(Issue.STATUS_OPEN);
 
   // output
-  IssueCache issueCache;
-
-  IssueComputation sut;
+  IssueCache outputIssues;
 
   @Before
   public void setUp() throws IOException {
     when(ruleCache.get(RULE_KEY)).thenReturn(rule);
-    issueCache = new IssueCache(temp.newFile(), System2.INSTANCE);
-    sut = new IssueComputation(ruleCache, lineCache, scmAccountCache, issueCache);
+    outputIssues = new IssueCache(temp.newFile(), System2.INSTANCE);
+    sut = new IssueComputation(ruleCache, lineCache, scmAccountCache, outputIssues);
   }
 
   @Test
   public void store_issues_on_disk() throws Exception {
     process();
 
-    assertThat(Iterators.getOnlyElement(issueCache.traverse()).key()).isEqualTo("ISSUE_A");
+    assertThat(Iterators.getOnlyElement(outputIssues.traverse()).key()).isEqualTo("ISSUE_A");
   }
 
   @Test
   public void copy_rule_tags_on_new_issues() throws Exception {
-    issue.setNew(true);
+    inputIssue.setIsNew(true);
     rule.setTags(ImmutableSet.of("bug", "performance"));
     rule.setSystemTags(ImmutableSet.of("blocker"));
 
     process();
 
-    assertThat(Iterators.getOnlyElement(issueCache.traverse()).tags()).containsOnly("blocker", "bug", "performance");
+    assertThat(Iterators.getOnlyElement(outputIssues.traverse()).tags()).containsOnly("blocker", "bug", "performance");
   }
 
   @Test
   public void do_not_copy_rule_tags_on_existing_issues() throws Exception {
-    issue.setNew(false);
+    inputIssue.setIsNew(false);
     rule.setTags(ImmutableSet.of("bug", "performance"));
     rule.setSystemTags(ImmutableSet.of("blocker"));
 
     process();
 
-    assertThat(Iterators.getOnlyElement(issueCache.traverse()).tags()).isEmpty();
+    assertThat(Iterators.getOnlyElement(outputIssues.traverse()).tags()).isEmpty();
   }
 
   @Test
   public void guess_author_of_new_issues() throws Exception {
-    issue.setNew(true);
-    issue.setLine(3);
+    inputIssue.setIsNew(true);
+    inputIssue.setLine(3);
     when(lineCache.lineAuthor(3)).thenReturn("charlie");
 
     process();
 
-    assertThat(Iterators.getOnlyElement(issueCache.traverse()).authorLogin()).isEqualTo("charlie");
+    assertThat(Iterators.getOnlyElement(outputIssues.traverse()).authorLogin()).isEqualTo("charlie");
   }
 
   @Test
   public void do_not_fail_if_missing_author_for_new_issues() throws Exception {
-    issue.setNew(true);
-    issue.setLine(3);
+    inputIssue.setIsNew(true);
+    inputIssue.setLine(3);
     when(lineCache.lineAuthor(3)).thenReturn(null);
 
     process();
 
-    assertThat(Iterators.getOnlyElement(issueCache.traverse()).authorLogin()).isNull();
+    assertThat(Iterators.getOnlyElement(outputIssues.traverse()).authorLogin()).isNull();
   }
 
   @Test
   public void do_not_guess_author_of_existing_issues() throws Exception {
-    issue.setNew(false);
-    issue.setLine(3);
+    inputIssue.setIsNew(false);
+    inputIssue.setLine(3);
     when(lineCache.lineAuthor(3)).thenReturn("charlie");
 
     process();
 
-    assertThat(Iterators.getOnlyElement(issueCache.traverse()).authorLogin()).isNull();
+    assertThat(Iterators.getOnlyElement(outputIssues.traverse()).authorLogin()).isNull();
   }
 
   @Test
   public void auto_assign_new_issues() throws Exception {
-    issue.setNew(true);
-    issue.setAuthorLogin("charlie");
+    inputIssue.setIsNew(true);
+    inputIssue.setAuthorLogin("charlie");
     when(scmAccountCache.getNullable("charlie")).thenReturn("char.lie");
 
     process();
 
-    assertThat(Iterators.getOnlyElement(issueCache.traverse()).assignee()).isEqualTo("char.lie");
+    assertThat(Iterators.getOnlyElement(outputIssues.traverse()).assignee()).isEqualTo("char.lie");
   }
 
   @Test
   public void do_not_auto_assign_existing_issues() throws Exception {
-    issue.setNew(false);
-    issue.setAuthorLogin("charlie");
+    inputIssue.setIsNew(false);
+    inputIssue.setAuthorLogin("charlie");
     when(scmAccountCache.getNullable("charlie")).thenReturn("char.lie");
 
     process();
 
-    assertThat(Iterators.getOnlyElement(issueCache.traverse()).assignee()).isNull();
+    assertThat(Iterators.getOnlyElement(outputIssues.traverse()).assignee()).isNull();
   }
 
   @Test
   public void do_not_override_author_and_assignee_set_by_old_batch_plugins() throws Exception {
-    issue.setNew(true);
+    inputIssue.setIsNew(true);
 
     // these fields were provided during project analysis, for instance
     // by developer cockpit or issue-assign plugins
-    issue.setAuthorLogin("charlie");
-    issue.setAssignee("cabu");
+    inputIssue.setAuthorLogin("charlie");
+    inputIssue.setAssignee("cabu");
 
     process();
 
     // keep the values, without trying to update them
-    DefaultIssue cachedIssue = Iterators.getOnlyElement(issueCache.traverse());
+    DefaultIssue cachedIssue = Iterators.getOnlyElement(outputIssues.traverse());
     assertThat(cachedIssue.assignee()).isEqualTo("cabu");
     assertThat(cachedIssue.authorLogin()).isEqualTo("charlie");
     verifyZeroInteractions(scmAccountCache);
   }
 
   private void process() {
-    sut.processComponentIssues("FILE_A", Arrays.asList(issue));
+    sut.processComponentIssues(mock(ComputationContext.class, Mockito.RETURNS_DEEP_STUBS), "FILE_A", Arrays.asList(inputIssue.build()));
     sut.afterReportProcessing();
   }
 }
index 11ca06ccd1270205f57cf4bec5a551aab86afac7..ae1e8ee85c77ad91ec96bc05f9754b2f6c533314 100644 (file)
@@ -33,7 +33,7 @@ public class ComputationStepsTest {
     ComputationSteps registry = new ComputationSteps(
       // unordered
       mock(ApplyPermissionsStep.class),
-      mock(DigestReportStep.class),
+      mock(ParseReportStep.class),
       mock(IndexSourceLinesStep.class),
       mock(IndexViewsStep.class),
       mock(PurgeRemovedViewsStep.class),
@@ -45,14 +45,14 @@ public class ComputationStepsTest {
       mock(IndexComponentsStep.class));
 
     assertThat(registry.orderedSteps()).hasSize(11);
-    assertThat(registry.orderedSteps().get(0)).isInstanceOf(DigestReportStep.class);
+    assertThat(registry.orderedSteps().get(0)).isInstanceOf(ParseReportStep.class);
     assertThat(registry.orderedSteps().get(10)).isInstanceOf(SendIssueNotificationsStep.class);
   }
 
   @Test
   public void fail_if_a_step_is_not_registered_in_picocontainer() throws Exception {
     try {
-      new ComputationSteps(mock(DigestReportStep.class));
+      new ComputationSteps(mock(ParseReportStep.class));
       fail();
     } catch (IllegalStateException e) {
       assertThat(e).hasMessageContaining("Component not found");
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/DigestReportStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/DigestReportStepTest.java
deleted file mode 100644 (file)
index 7b83dd1..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.
- */
-/*
-* SonarQube, open source software quality management tool.
-* Copyright (C) 2008-2014 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.computation.step;
-
-import org.junit.Test;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.server.computation.AnalysisReportService;
-import org.sonar.server.computation.ComputationContext;
-
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class DigestReportStepTest {
-
-  @Test
-  public void call_service_method() throws Exception {
-    AnalysisReportService service = mock(AnalysisReportService.class);
-    DigestReportStep sut = new DigestReportStep(service);
-    ComputationContext context = new ComputationContext(mock(AnalysisReportDto.class), mock(ComponentDto.class), null);
-
-    sut.execute(context);
-
-    verify(service).digest(eq(context));
-  }
-}
index fe5c016b4ee0a0cf01c742706fd9fc6daf250e32..cc4a4878a6d8fd60cc9aa8bf778f32ba4cb5926c 100644 (file)
@@ -21,9 +21,8 @@
 package org.sonar.server.computation.step;
 
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.sonar.batch.protocol.output.BatchOutputReader;
 import org.sonar.core.component.ComponentDto;
 import org.sonar.core.computation.db.AnalysisReportDto;
 import org.sonar.core.resource.ResourceIndexerDao;
@@ -35,9 +34,6 @@ import static org.mockito.Mockito.*;
 
 public class IndexComponentsStepTest {
 
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
   IndexComponentsStep sut;
   ResourceIndexerDao resourceIndexerDao;
 
@@ -51,7 +47,7 @@ public class IndexComponentsStepTest {
   public void call_indexProject_of_dao() throws IOException {
     ComponentDto project = mock(ComponentDto.class);
     when(project.getId()).thenReturn(123L);
-    ComputationContext context = new ComputationContext(mock(AnalysisReportDto.class), project, temp.newFolder());
+    ComputationContext context = new ComputationContext(mock(AnalysisReportDto.class), project, mock(BatchOutputReader.class));
 
     sut.execute(context);
 
index 29d28001a03ed42831263b31a1332ef3949eb72b..f858ce7a2fc07662ea58c0d78da28af95ae14012 100644 (file)
@@ -25,6 +25,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.mockito.Mockito;
+import org.sonar.batch.protocol.output.BatchOutputReader;
 import org.sonar.core.component.ComponentDto;
 import org.sonar.core.computation.db.AnalysisReportDto;
 import org.sonar.core.computation.dbcleaner.ProjectCleaner;
@@ -58,8 +59,7 @@ public class PurgeDatastoresStepTest {
     ComponentDto project = mock(ComponentDto.class);
     when(project.getId()).thenReturn(123L);
     when(project.uuid()).thenReturn("UUID-1234");
-    ComputationContext context = new ComputationContext(mock(AnalysisReportDto.class), project,
-      temp.newFolder());
+    ComputationContext context = new ComputationContext(mock(AnalysisReportDto.class), project, mock(BatchOutputReader.class));
 
     sut.execute(context);
 
index af515d5995027bc5abea0c09b60c63ec92e47a05..72758f31f043a90fe94159662fc65aaaee242465 100644 (file)
@@ -24,9 +24,9 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
-import org.junit.rules.TemporaryFolder;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
+import org.sonar.batch.protocol.output.BatchOutputReader;
 import org.sonar.core.computation.db.AnalysisReportDto;
 import org.sonar.core.persistence.DbTester;
 import org.sonar.server.component.ComponentTesting;
@@ -46,10 +46,7 @@ public class SwitchSnapshotStepTest {
   @Rule
   public DbTester db = new DbTester();
 
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  private SwitchSnapshotStep sut;
+  SwitchSnapshotStep sut;
 
   @Before
   public void before() {
@@ -62,7 +59,7 @@ public class SwitchSnapshotStepTest {
   public void one_switch_with_a_snapshot_and_his_children() throws IOException {
     db.prepareDbUnit(getClass(), "snapshots.xml");
     ComputationContext context = new ComputationContext(AnalysisReportDto.newForTests(1L).setSnapshotId(1L),
-      ComponentTesting.newProjectDto(), temp.newFolder());
+      ComponentTesting.newProjectDto(), mock(BatchOutputReader.class));
 
     sut.execute(context);
 
@@ -73,7 +70,7 @@ public class SwitchSnapshotStepTest {
   public void throw_IllegalStateException_when_not_finding_snapshot() throws IOException {
     db.prepareDbUnit(getClass(), "empty.xml");
     ComputationContext context = new ComputationContext(AnalysisReportDto.newForTests(1L).setSnapshotId(1L),
-      ComponentTesting.newProjectDto(), temp.newFolder());
+      ComponentTesting.newProjectDto(), mock(BatchOutputReader.class));
 
     sut.execute(context);
   }
diff --git a/sonar-batch-protocol/compile_protobuf.sh b/sonar-batch-protocol/compile_protobuf.sh
new file mode 100644 (file)
index 0000000..f2d14c4
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+OUTPUT_DIR="src/main/gen-java"
+
+mkdir -p ${OUTPUT_DIR}
+protoc --proto_path=src/main/protobuf --java_out=${OUTPUT_DIR} src/main/protobuf/*.proto
index a221b25fbe6fb90e2c2104addf76e9711040b336..399c4a242e027fc441e2ca52cb533ddd98f2de8d 100644 (file)
   <description>Classes used for communication between batch and server</description>
 
   <dependencies>
+    <dependency>
+      <groupId>com.google.protobuf</groupId>
+      <artifactId>protobuf-java</artifactId>
+    </dependency>
     <dependency>
       <groupId>com.google.code.gson</groupId>
       <artifactId>gson</artifactId>
 
   <build>
     <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-source</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>src/main/gen-java</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
diff --git a/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/Constants.java b/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/Constants.java
new file mode 100644 (file)
index 0000000..f9cd2f3
--- /dev/null
@@ -0,0 +1,269 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: constants.proto
+
+package org.sonar.batch.protocol;
+
+public final class Constants {
+  private Constants() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+  }
+  /**
+   * Protobuf enum {@code Severity}
+   */
+  public enum Severity
+      implements com.google.protobuf.ProtocolMessageEnum {
+    /**
+     * <code>INFO = 0;</code>
+     */
+    INFO(0, 0),
+    /**
+     * <code>MINOR = 1;</code>
+     */
+    MINOR(1, 1),
+    /**
+     * <code>MAJOR = 2;</code>
+     */
+    MAJOR(2, 2),
+    /**
+     * <code>CRITICAL = 3;</code>
+     */
+    CRITICAL(3, 3),
+    /**
+     * <code>BLOCKER = 4;</code>
+     */
+    BLOCKER(4, 4),
+    ;
+
+    /**
+     * <code>INFO = 0;</code>
+     */
+    public static final int INFO_VALUE = 0;
+    /**
+     * <code>MINOR = 1;</code>
+     */
+    public static final int MINOR_VALUE = 1;
+    /**
+     * <code>MAJOR = 2;</code>
+     */
+    public static final int MAJOR_VALUE = 2;
+    /**
+     * <code>CRITICAL = 3;</code>
+     */
+    public static final int CRITICAL_VALUE = 3;
+    /**
+     * <code>BLOCKER = 4;</code>
+     */
+    public static final int BLOCKER_VALUE = 4;
+
+
+    public final int getNumber() { return value; }
+
+    public static Severity valueOf(int value) {
+      switch (value) {
+        case 0: return INFO;
+        case 1: return MINOR;
+        case 2: return MAJOR;
+        case 3: return CRITICAL;
+        case 4: return BLOCKER;
+        default: return null;
+      }
+    }
+
+    public static com.google.protobuf.Internal.EnumLiteMap<Severity>
+        internalGetValueMap() {
+      return internalValueMap;
+    }
+    private static com.google.protobuf.Internal.EnumLiteMap<Severity>
+        internalValueMap =
+          new com.google.protobuf.Internal.EnumLiteMap<Severity>() {
+            public Severity findValueByNumber(int number) {
+              return Severity.valueOf(number);
+            }
+          };
+
+    public final com.google.protobuf.Descriptors.EnumValueDescriptor
+        getValueDescriptor() {
+      return getDescriptor().getValues().get(index);
+    }
+    public final com.google.protobuf.Descriptors.EnumDescriptor
+        getDescriptorForType() {
+      return getDescriptor();
+    }
+    public static final com.google.protobuf.Descriptors.EnumDescriptor
+        getDescriptor() {
+      return org.sonar.batch.protocol.Constants.getDescriptor().getEnumTypes().get(0);
+    }
+
+    private static final Severity[] VALUES = values();
+
+    public static Severity valueOf(
+        com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
+      if (desc.getType() != getDescriptor()) {
+        throw new java.lang.IllegalArgumentException(
+          "EnumValueDescriptor is not for this type.");
+      }
+      return VALUES[desc.getIndex()];
+    }
+
+    private final int index;
+    private final int value;
+
+    private Severity(int index, int value) {
+      this.index = index;
+      this.value = value;
+    }
+
+    // @@protoc_insertion_point(enum_scope:Severity)
+  }
+
+  /**
+   * Protobuf enum {@code ComponentType}
+   */
+  public enum ComponentType
+      implements com.google.protobuf.ProtocolMessageEnum {
+    /**
+     * <code>PROJECT = 0;</code>
+     */
+    PROJECT(0, 0),
+    /**
+     * <code>MODULE = 1;</code>
+     */
+    MODULE(1, 1),
+    /**
+     * <code>DIRECTORY = 2;</code>
+     */
+    DIRECTORY(2, 2),
+    /**
+     * <code>FILE = 3;</code>
+     */
+    FILE(3, 3),
+    /**
+     * <code>VIEW = 4;</code>
+     */
+    VIEW(4, 4),
+    /**
+     * <code>SUBVIEW = 5;</code>
+     */
+    SUBVIEW(5, 5),
+    ;
+
+    /**
+     * <code>PROJECT = 0;</code>
+     */
+    public static final int PROJECT_VALUE = 0;
+    /**
+     * <code>MODULE = 1;</code>
+     */
+    public static final int MODULE_VALUE = 1;
+    /**
+     * <code>DIRECTORY = 2;</code>
+     */
+    public static final int DIRECTORY_VALUE = 2;
+    /**
+     * <code>FILE = 3;</code>
+     */
+    public static final int FILE_VALUE = 3;
+    /**
+     * <code>VIEW = 4;</code>
+     */
+    public static final int VIEW_VALUE = 4;
+    /**
+     * <code>SUBVIEW = 5;</code>
+     */
+    public static final int SUBVIEW_VALUE = 5;
+
+
+    public final int getNumber() { return value; }
+
+    public static ComponentType valueOf(int value) {
+      switch (value) {
+        case 0: return PROJECT;
+        case 1: return MODULE;
+        case 2: return DIRECTORY;
+        case 3: return FILE;
+        case 4: return VIEW;
+        case 5: return SUBVIEW;
+        default: return null;
+      }
+    }
+
+    public static com.google.protobuf.Internal.EnumLiteMap<ComponentType>
+        internalGetValueMap() {
+      return internalValueMap;
+    }
+    private static com.google.protobuf.Internal.EnumLiteMap<ComponentType>
+        internalValueMap =
+          new com.google.protobuf.Internal.EnumLiteMap<ComponentType>() {
+            public ComponentType findValueByNumber(int number) {
+              return ComponentType.valueOf(number);
+            }
+          };
+
+    public final com.google.protobuf.Descriptors.EnumValueDescriptor
+        getValueDescriptor() {
+      return getDescriptor().getValues().get(index);
+    }
+    public final com.google.protobuf.Descriptors.EnumDescriptor
+        getDescriptorForType() {
+      return getDescriptor();
+    }
+    public static final com.google.protobuf.Descriptors.EnumDescriptor
+        getDescriptor() {
+      return org.sonar.batch.protocol.Constants.getDescriptor().getEnumTypes().get(1);
+    }
+
+    private static final ComponentType[] VALUES = values();
+
+    public static ComponentType valueOf(
+        com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
+      if (desc.getType() != getDescriptor()) {
+        throw new java.lang.IllegalArgumentException(
+          "EnumValueDescriptor is not for this type.");
+      }
+      return VALUES[desc.getIndex()];
+    }
+
+    private final int index;
+    private final int value;
+
+    private ComponentType(int index, int value) {
+      this.index = index;
+      this.value = value;
+    }
+
+    // @@protoc_insertion_point(enum_scope:ComponentType)
+  }
+
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\017constants.proto*E\n\010Severity\022\010\n\004INFO\020\000\022" +
+      "\t\n\005MINOR\020\001\022\t\n\005MAJOR\020\002\022\014\n\010CRITICAL\020\003\022\013\n\007B" +
+      "LOCKER\020\004*X\n\rComponentType\022\013\n\007PROJECT\020\000\022\n" +
+      "\n\006MODULE\020\001\022\r\n\tDIRECTORY\020\002\022\010\n\004FILE\020\003\022\010\n\004V" +
+      "IEW\020\004\022\013\n\007SUBVIEW\020\005B\034\n\030org.sonar.batch.pr" +
+      "otocolH\001"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+        new com.google.protobuf.Descriptors.FileDescriptor.    InternalDescriptorAssigner() {
+          public com.google.protobuf.ExtensionRegistry assignDescriptors(
+              com.google.protobuf.Descriptors.FileDescriptor root) {
+            descriptor = root;
+            return null;
+          }
+        };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        }, assigner);
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchOutput.java b/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchOutput.java
new file mode 100644 (file)
index 0000000..d42f92e
--- /dev/null
@@ -0,0 +1,6470 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: batch_output.proto
+
+package org.sonar.batch.protocol.output;
+
+public final class BatchOutput {
+  private BatchOutput() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+  }
+  public interface ReportMetadataOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:ReportMetadata)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>optional int64 analysis_date = 1;</code>
+     */
+    boolean hasAnalysisDate();
+    /**
+     * <code>optional int64 analysis_date = 1;</code>
+     */
+    long getAnalysisDate();
+
+    /**
+     * <code>optional string project_key = 2;</code>
+     */
+    boolean hasProjectKey();
+    /**
+     * <code>optional string project_key = 2;</code>
+     */
+    java.lang.String getProjectKey();
+    /**
+     * <code>optional string project_key = 2;</code>
+     */
+    com.google.protobuf.ByteString
+        getProjectKeyBytes();
+
+    /**
+     * <code>optional int32 root_component_ref = 3;</code>
+     */
+    boolean hasRootComponentRef();
+    /**
+     * <code>optional int32 root_component_ref = 3;</code>
+     */
+    int getRootComponentRef();
+  }
+  /**
+   * Protobuf type {@code ReportMetadata}
+   */
+  public static final class ReportMetadata extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:ReportMetadata)
+      ReportMetadataOrBuilder {
+    // Use ReportMetadata.newBuilder() to construct.
+    private ReportMetadata(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private ReportMetadata(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final ReportMetadata defaultInstance;
+    public static ReportMetadata getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public ReportMetadata getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private ReportMetadata(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              bitField0_ |= 0x00000001;
+              analysisDate_ = input.readInt64();
+              break;
+            }
+            case 18: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000002;
+              projectKey_ = bs;
+              break;
+            }
+            case 24: {
+              bitField0_ |= 0x00000004;
+              rootComponentRef_ = input.readInt32();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportMetadata_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportMetadata_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.sonar.batch.protocol.output.BatchOutput.ReportMetadata.class, org.sonar.batch.protocol.output.BatchOutput.ReportMetadata.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<ReportMetadata> PARSER =
+        new com.google.protobuf.AbstractParser<ReportMetadata>() {
+      public ReportMetadata parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new ReportMetadata(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<ReportMetadata> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    public static final int ANALYSIS_DATE_FIELD_NUMBER = 1;
+    private long analysisDate_;
+    /**
+     * <code>optional int64 analysis_date = 1;</code>
+     */
+    public boolean hasAnalysisDate() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>optional int64 analysis_date = 1;</code>
+     */
+    public long getAnalysisDate() {
+      return analysisDate_;
+    }
+
+    public static final int PROJECT_KEY_FIELD_NUMBER = 2;
+    private java.lang.Object projectKey_;
+    /**
+     * <code>optional string project_key = 2;</code>
+     */
+    public boolean hasProjectKey() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>optional string project_key = 2;</code>
+     */
+    public java.lang.String getProjectKey() {
+      java.lang.Object ref = projectKey_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          projectKey_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string project_key = 2;</code>
+     */
+    public com.google.protobuf.ByteString
+        getProjectKeyBytes() {
+      java.lang.Object ref = projectKey_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        projectKey_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int ROOT_COMPONENT_REF_FIELD_NUMBER = 3;
+    private int rootComponentRef_;
+    /**
+     * <code>optional int32 root_component_ref = 3;</code>
+     */
+    public boolean hasRootComponentRef() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional int32 root_component_ref = 3;</code>
+     */
+    public int getRootComponentRef() {
+      return rootComponentRef_;
+    }
+
+    private void initFields() {
+      analysisDate_ = 0L;
+      projectKey_ = "";
+      rootComponentRef_ = 0;
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeInt64(1, analysisDate_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeBytes(2, getProjectKeyBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeInt32(3, rootComponentRef_);
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(1, analysisDate_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(2, getProjectKeyBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(3, rootComponentRef_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportMetadata parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportMetadata parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportMetadata parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportMetadata parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportMetadata parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportMetadata parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportMetadata parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportMetadata parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportMetadata parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportMetadata parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.sonar.batch.protocol.output.BatchOutput.ReportMetadata prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code ReportMetadata}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:ReportMetadata)
+        org.sonar.batch.protocol.output.BatchOutput.ReportMetadataOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportMetadata_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportMetadata_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.sonar.batch.protocol.output.BatchOutput.ReportMetadata.class, org.sonar.batch.protocol.output.BatchOutput.ReportMetadata.Builder.class);
+      }
+
+      // Construct using org.sonar.batch.protocol.output.BatchOutput.ReportMetadata.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        analysisDate_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        projectKey_ = "";
+        bitField0_ = (bitField0_ & ~0x00000002);
+        rootComponentRef_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000004);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportMetadata_descriptor;
+      }
+
+      public org.sonar.batch.protocol.output.BatchOutput.ReportMetadata getDefaultInstanceForType() {
+        return org.sonar.batch.protocol.output.BatchOutput.ReportMetadata.getDefaultInstance();
+      }
+
+      public org.sonar.batch.protocol.output.BatchOutput.ReportMetadata build() {
+        org.sonar.batch.protocol.output.BatchOutput.ReportMetadata result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.sonar.batch.protocol.output.BatchOutput.ReportMetadata buildPartial() {
+        org.sonar.batch.protocol.output.BatchOutput.ReportMetadata result = new org.sonar.batch.protocol.output.BatchOutput.ReportMetadata(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.analysisDate_ = analysisDate_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.projectKey_ = projectKey_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.rootComponentRef_ = rootComponentRef_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.sonar.batch.protocol.output.BatchOutput.ReportMetadata) {
+          return mergeFrom((org.sonar.batch.protocol.output.BatchOutput.ReportMetadata)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.sonar.batch.protocol.output.BatchOutput.ReportMetadata other) {
+        if (other == org.sonar.batch.protocol.output.BatchOutput.ReportMetadata.getDefaultInstance()) return this;
+        if (other.hasAnalysisDate()) {
+          setAnalysisDate(other.getAnalysisDate());
+        }
+        if (other.hasProjectKey()) {
+          bitField0_ |= 0x00000002;
+          projectKey_ = other.projectKey_;
+          onChanged();
+        }
+        if (other.hasRootComponentRef()) {
+          setRootComponentRef(other.getRootComponentRef());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.sonar.batch.protocol.output.BatchOutput.ReportMetadata parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.sonar.batch.protocol.output.BatchOutput.ReportMetadata) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      private long analysisDate_ ;
+      /**
+       * <code>optional int64 analysis_date = 1;</code>
+       */
+      public boolean hasAnalysisDate() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>optional int64 analysis_date = 1;</code>
+       */
+      public long getAnalysisDate() {
+        return analysisDate_;
+      }
+      /**
+       * <code>optional int64 analysis_date = 1;</code>
+       */
+      public Builder setAnalysisDate(long value) {
+        bitField0_ |= 0x00000001;
+        analysisDate_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int64 analysis_date = 1;</code>
+       */
+      public Builder clearAnalysisDate() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        analysisDate_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object projectKey_ = "";
+      /**
+       * <code>optional string project_key = 2;</code>
+       */
+      public boolean hasProjectKey() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>optional string project_key = 2;</code>
+       */
+      public java.lang.String getProjectKey() {
+        java.lang.Object ref = projectKey_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            projectKey_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string project_key = 2;</code>
+       */
+      public com.google.protobuf.ByteString
+          getProjectKeyBytes() {
+        java.lang.Object ref = projectKey_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          projectKey_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string project_key = 2;</code>
+       */
+      public Builder setProjectKey(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        projectKey_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string project_key = 2;</code>
+       */
+      public Builder clearProjectKey() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        projectKey_ = getDefaultInstance().getProjectKey();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string project_key = 2;</code>
+       */
+      public Builder setProjectKeyBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        projectKey_ = value;
+        onChanged();
+        return this;
+      }
+
+      private int rootComponentRef_ ;
+      /**
+       * <code>optional int32 root_component_ref = 3;</code>
+       */
+      public boolean hasRootComponentRef() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional int32 root_component_ref = 3;</code>
+       */
+      public int getRootComponentRef() {
+        return rootComponentRef_;
+      }
+      /**
+       * <code>optional int32 root_component_ref = 3;</code>
+       */
+      public Builder setRootComponentRef(int value) {
+        bitField0_ |= 0x00000004;
+        rootComponentRef_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 root_component_ref = 3;</code>
+       */
+      public Builder clearRootComponentRef() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        rootComponentRef_ = 0;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:ReportMetadata)
+    }
+
+    static {
+      defaultInstance = new ReportMetadata(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:ReportMetadata)
+  }
+
+  public interface ReportComponentOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:ReportComponent)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>optional int32 ref = 1;</code>
+     */
+    boolean hasRef();
+    /**
+     * <code>optional int32 ref = 1;</code>
+     */
+    int getRef();
+
+    /**
+     * <code>optional string path = 2;</code>
+     */
+    boolean hasPath();
+    /**
+     * <code>optional string path = 2;</code>
+     */
+    java.lang.String getPath();
+    /**
+     * <code>optional string path = 2;</code>
+     */
+    com.google.protobuf.ByteString
+        getPathBytes();
+
+    /**
+     * <code>optional string name = 3;</code>
+     */
+    boolean hasName();
+    /**
+     * <code>optional string name = 3;</code>
+     */
+    java.lang.String getName();
+    /**
+     * <code>optional string name = 3;</code>
+     */
+    com.google.protobuf.ByteString
+        getNameBytes();
+
+    /**
+     * <code>optional .ComponentType type = 4;</code>
+     */
+    boolean hasType();
+    /**
+     * <code>optional .ComponentType type = 4;</code>
+     */
+    org.sonar.batch.protocol.Constants.ComponentType getType();
+
+    /**
+     * <code>optional bool is_test = 5;</code>
+     */
+    boolean hasIsTest();
+    /**
+     * <code>optional bool is_test = 5;</code>
+     */
+    boolean getIsTest();
+
+    /**
+     * <code>optional string language = 6;</code>
+     */
+    boolean hasLanguage();
+    /**
+     * <code>optional string language = 6;</code>
+     */
+    java.lang.String getLanguage();
+    /**
+     * <code>optional string language = 6;</code>
+     */
+    com.google.protobuf.ByteString
+        getLanguageBytes();
+
+    /**
+     * <code>repeated int32 child_refs = 7;</code>
+     */
+    java.util.List<java.lang.Integer> getChildRefsList();
+    /**
+     * <code>repeated int32 child_refs = 7;</code>
+     */
+    int getChildRefsCount();
+    /**
+     * <code>repeated int32 child_refs = 7;</code>
+     */
+    int getChildRefs(int index);
+
+    /**
+     * <code>optional int32 snapshot_id = 8;</code>
+     *
+     * <pre>
+     * temporary fields during development of computation stack
+     * </pre>
+     */
+    boolean hasSnapshotId();
+    /**
+     * <code>optional int32 snapshot_id = 8;</code>
+     *
+     * <pre>
+     * temporary fields during development of computation stack
+     * </pre>
+     */
+    int getSnapshotId();
+
+    /**
+     * <code>optional string uuid = 9;</code>
+     */
+    boolean hasUuid();
+    /**
+     * <code>optional string uuid = 9;</code>
+     */
+    java.lang.String getUuid();
+    /**
+     * <code>optional string uuid = 9;</code>
+     */
+    com.google.protobuf.ByteString
+        getUuidBytes();
+  }
+  /**
+   * Protobuf type {@code ReportComponent}
+   */
+  public static final class ReportComponent extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:ReportComponent)
+      ReportComponentOrBuilder {
+    // Use ReportComponent.newBuilder() to construct.
+    private ReportComponent(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private ReportComponent(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final ReportComponent defaultInstance;
+    public static ReportComponent getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public ReportComponent getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private ReportComponent(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              bitField0_ |= 0x00000001;
+              ref_ = input.readInt32();
+              break;
+            }
+            case 18: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000002;
+              path_ = bs;
+              break;
+            }
+            case 26: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000004;
+              name_ = bs;
+              break;
+            }
+            case 32: {
+              int rawValue = input.readEnum();
+              org.sonar.batch.protocol.Constants.ComponentType value = org.sonar.batch.protocol.Constants.ComponentType.valueOf(rawValue);
+              if (value == null) {
+                unknownFields.mergeVarintField(4, rawValue);
+              } else {
+                bitField0_ |= 0x00000008;
+                type_ = value;
+              }
+              break;
+            }
+            case 40: {
+              bitField0_ |= 0x00000010;
+              isTest_ = input.readBool();
+              break;
+            }
+            case 50: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000020;
+              language_ = bs;
+              break;
+            }
+            case 56: {
+              if (!((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
+                childRefs_ = new java.util.ArrayList<java.lang.Integer>();
+                mutable_bitField0_ |= 0x00000040;
+              }
+              childRefs_.add(input.readInt32());
+              break;
+            }
+            case 58: {
+              int length = input.readRawVarint32();
+              int limit = input.pushLimit(length);
+              if (!((mutable_bitField0_ & 0x00000040) == 0x00000040) && input.getBytesUntilLimit() > 0) {
+                childRefs_ = new java.util.ArrayList<java.lang.Integer>();
+                mutable_bitField0_ |= 0x00000040;
+              }
+              while (input.getBytesUntilLimit() > 0) {
+                childRefs_.add(input.readInt32());
+              }
+              input.popLimit(limit);
+              break;
+            }
+            case 64: {
+              bitField0_ |= 0x00000040;
+              snapshotId_ = input.readInt32();
+              break;
+            }
+            case 74: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000080;
+              uuid_ = bs;
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        if (((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
+          childRefs_ = java.util.Collections.unmodifiableList(childRefs_);
+        }
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportComponent_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportComponent_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.sonar.batch.protocol.output.BatchOutput.ReportComponent.class, org.sonar.batch.protocol.output.BatchOutput.ReportComponent.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<ReportComponent> PARSER =
+        new com.google.protobuf.AbstractParser<ReportComponent>() {
+      public ReportComponent parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new ReportComponent(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<ReportComponent> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    public static final int REF_FIELD_NUMBER = 1;
+    private int ref_;
+    /**
+     * <code>optional int32 ref = 1;</code>
+     */
+    public boolean hasRef() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>optional int32 ref = 1;</code>
+     */
+    public int getRef() {
+      return ref_;
+    }
+
+    public static final int PATH_FIELD_NUMBER = 2;
+    private java.lang.Object path_;
+    /**
+     * <code>optional string path = 2;</code>
+     */
+    public boolean hasPath() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>optional string path = 2;</code>
+     */
+    public java.lang.String getPath() {
+      java.lang.Object ref = path_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          path_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string path = 2;</code>
+     */
+    public com.google.protobuf.ByteString
+        getPathBytes() {
+      java.lang.Object ref = path_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        path_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int NAME_FIELD_NUMBER = 3;
+    private java.lang.Object name_;
+    /**
+     * <code>optional string name = 3;</code>
+     */
+    public boolean hasName() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional string name = 3;</code>
+     */
+    public java.lang.String getName() {
+      java.lang.Object ref = name_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          name_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string name = 3;</code>
+     */
+    public com.google.protobuf.ByteString
+        getNameBytes() {
+      java.lang.Object ref = name_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        name_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int TYPE_FIELD_NUMBER = 4;
+    private org.sonar.batch.protocol.Constants.ComponentType type_;
+    /**
+     * <code>optional .ComponentType type = 4;</code>
+     */
+    public boolean hasType() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>optional .ComponentType type = 4;</code>
+     */
+    public org.sonar.batch.protocol.Constants.ComponentType getType() {
+      return type_;
+    }
+
+    public static final int IS_TEST_FIELD_NUMBER = 5;
+    private boolean isTest_;
+    /**
+     * <code>optional bool is_test = 5;</code>
+     */
+    public boolean hasIsTest() {
+      return ((bitField0_ & 0x00000010) == 0x00000010);
+    }
+    /**
+     * <code>optional bool is_test = 5;</code>
+     */
+    public boolean getIsTest() {
+      return isTest_;
+    }
+
+    public static final int LANGUAGE_FIELD_NUMBER = 6;
+    private java.lang.Object language_;
+    /**
+     * <code>optional string language = 6;</code>
+     */
+    public boolean hasLanguage() {
+      return ((bitField0_ & 0x00000020) == 0x00000020);
+    }
+    /**
+     * <code>optional string language = 6;</code>
+     */
+    public java.lang.String getLanguage() {
+      java.lang.Object ref = language_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          language_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string language = 6;</code>
+     */
+    public com.google.protobuf.ByteString
+        getLanguageBytes() {
+      java.lang.Object ref = language_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        language_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int CHILD_REFS_FIELD_NUMBER = 7;
+    private java.util.List<java.lang.Integer> childRefs_;
+    /**
+     * <code>repeated int32 child_refs = 7;</code>
+     */
+    public java.util.List<java.lang.Integer>
+        getChildRefsList() {
+      return childRefs_;
+    }
+    /**
+     * <code>repeated int32 child_refs = 7;</code>
+     */
+    public int getChildRefsCount() {
+      return childRefs_.size();
+    }
+    /**
+     * <code>repeated int32 child_refs = 7;</code>
+     */
+    public int getChildRefs(int index) {
+      return childRefs_.get(index);
+    }
+
+    public static final int SNAPSHOT_ID_FIELD_NUMBER = 8;
+    private int snapshotId_;
+    /**
+     * <code>optional int32 snapshot_id = 8;</code>
+     *
+     * <pre>
+     * temporary fields during development of computation stack
+     * </pre>
+     */
+    public boolean hasSnapshotId() {
+      return ((bitField0_ & 0x00000040) == 0x00000040);
+    }
+    /**
+     * <code>optional int32 snapshot_id = 8;</code>
+     *
+     * <pre>
+     * temporary fields during development of computation stack
+     * </pre>
+     */
+    public int getSnapshotId() {
+      return snapshotId_;
+    }
+
+    public static final int UUID_FIELD_NUMBER = 9;
+    private java.lang.Object uuid_;
+    /**
+     * <code>optional string uuid = 9;</code>
+     */
+    public boolean hasUuid() {
+      return ((bitField0_ & 0x00000080) == 0x00000080);
+    }
+    /**
+     * <code>optional string uuid = 9;</code>
+     */
+    public java.lang.String getUuid() {
+      java.lang.Object ref = uuid_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          uuid_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string uuid = 9;</code>
+     */
+    public com.google.protobuf.ByteString
+        getUuidBytes() {
+      java.lang.Object ref = uuid_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        uuid_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private void initFields() {
+      ref_ = 0;
+      path_ = "";
+      name_ = "";
+      type_ = org.sonar.batch.protocol.Constants.ComponentType.PROJECT;
+      isTest_ = false;
+      language_ = "";
+      childRefs_ = java.util.Collections.emptyList();
+      snapshotId_ = 0;
+      uuid_ = "";
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeInt32(1, ref_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeBytes(2, getPathBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeBytes(3, getNameBytes());
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeEnum(4, type_.getNumber());
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        output.writeBool(5, isTest_);
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        output.writeBytes(6, getLanguageBytes());
+      }
+      for (int i = 0; i < childRefs_.size(); i++) {
+        output.writeInt32(7, childRefs_.get(i));
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        output.writeInt32(8, snapshotId_);
+      }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        output.writeBytes(9, getUuidBytes());
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(1, ref_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(2, getPathBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(3, getNameBytes());
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeEnumSize(4, type_.getNumber());
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBoolSize(5, isTest_);
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(6, getLanguageBytes());
+      }
+      {
+        int dataSize = 0;
+        for (int i = 0; i < childRefs_.size(); i++) {
+          dataSize += com.google.protobuf.CodedOutputStream
+            .computeInt32SizeNoTag(childRefs_.get(i));
+        }
+        size += dataSize;
+        size += 1 * getChildRefsList().size();
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(8, snapshotId_);
+      }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(9, getUuidBytes());
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportComponent parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportComponent parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportComponent parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportComponent parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportComponent parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportComponent parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportComponent parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportComponent parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportComponent parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportComponent parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.sonar.batch.protocol.output.BatchOutput.ReportComponent prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code ReportComponent}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:ReportComponent)
+        org.sonar.batch.protocol.output.BatchOutput.ReportComponentOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportComponent_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportComponent_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.sonar.batch.protocol.output.BatchOutput.ReportComponent.class, org.sonar.batch.protocol.output.BatchOutput.ReportComponent.Builder.class);
+      }
+
+      // Construct using org.sonar.batch.protocol.output.BatchOutput.ReportComponent.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        ref_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        path_ = "";
+        bitField0_ = (bitField0_ & ~0x00000002);
+        name_ = "";
+        bitField0_ = (bitField0_ & ~0x00000004);
+        type_ = org.sonar.batch.protocol.Constants.ComponentType.PROJECT;
+        bitField0_ = (bitField0_ & ~0x00000008);
+        isTest_ = false;
+        bitField0_ = (bitField0_ & ~0x00000010);
+        language_ = "";
+        bitField0_ = (bitField0_ & ~0x00000020);
+        childRefs_ = java.util.Collections.emptyList();
+        bitField0_ = (bitField0_ & ~0x00000040);
+        snapshotId_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000080);
+        uuid_ = "";
+        bitField0_ = (bitField0_ & ~0x00000100);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportComponent_descriptor;
+      }
+
+      public org.sonar.batch.protocol.output.BatchOutput.ReportComponent getDefaultInstanceForType() {
+        return org.sonar.batch.protocol.output.BatchOutput.ReportComponent.getDefaultInstance();
+      }
+
+      public org.sonar.batch.protocol.output.BatchOutput.ReportComponent build() {
+        org.sonar.batch.protocol.output.BatchOutput.ReportComponent result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.sonar.batch.protocol.output.BatchOutput.ReportComponent buildPartial() {
+        org.sonar.batch.protocol.output.BatchOutput.ReportComponent result = new org.sonar.batch.protocol.output.BatchOutput.ReportComponent(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.ref_ = ref_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.path_ = path_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.name_ = name_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.type_ = type_;
+        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+          to_bitField0_ |= 0x00000010;
+        }
+        result.isTest_ = isTest_;
+        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
+          to_bitField0_ |= 0x00000020;
+        }
+        result.language_ = language_;
+        if (((bitField0_ & 0x00000040) == 0x00000040)) {
+          childRefs_ = java.util.Collections.unmodifiableList(childRefs_);
+          bitField0_ = (bitField0_ & ~0x00000040);
+        }
+        result.childRefs_ = childRefs_;
+        if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
+          to_bitField0_ |= 0x00000040;
+        }
+        result.snapshotId_ = snapshotId_;
+        if (((from_bitField0_ & 0x00000100) == 0x00000100)) {
+          to_bitField0_ |= 0x00000080;
+        }
+        result.uuid_ = uuid_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.sonar.batch.protocol.output.BatchOutput.ReportComponent) {
+          return mergeFrom((org.sonar.batch.protocol.output.BatchOutput.ReportComponent)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.sonar.batch.protocol.output.BatchOutput.ReportComponent other) {
+        if (other == org.sonar.batch.protocol.output.BatchOutput.ReportComponent.getDefaultInstance()) return this;
+        if (other.hasRef()) {
+          setRef(other.getRef());
+        }
+        if (other.hasPath()) {
+          bitField0_ |= 0x00000002;
+          path_ = other.path_;
+          onChanged();
+        }
+        if (other.hasName()) {
+          bitField0_ |= 0x00000004;
+          name_ = other.name_;
+          onChanged();
+        }
+        if (other.hasType()) {
+          setType(other.getType());
+        }
+        if (other.hasIsTest()) {
+          setIsTest(other.getIsTest());
+        }
+        if (other.hasLanguage()) {
+          bitField0_ |= 0x00000020;
+          language_ = other.language_;
+          onChanged();
+        }
+        if (!other.childRefs_.isEmpty()) {
+          if (childRefs_.isEmpty()) {
+            childRefs_ = other.childRefs_;
+            bitField0_ = (bitField0_ & ~0x00000040);
+          } else {
+            ensureChildRefsIsMutable();
+            childRefs_.addAll(other.childRefs_);
+          }
+          onChanged();
+        }
+        if (other.hasSnapshotId()) {
+          setSnapshotId(other.getSnapshotId());
+        }
+        if (other.hasUuid()) {
+          bitField0_ |= 0x00000100;
+          uuid_ = other.uuid_;
+          onChanged();
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.sonar.batch.protocol.output.BatchOutput.ReportComponent parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.sonar.batch.protocol.output.BatchOutput.ReportComponent) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      private int ref_ ;
+      /**
+       * <code>optional int32 ref = 1;</code>
+       */
+      public boolean hasRef() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>optional int32 ref = 1;</code>
+       */
+      public int getRef() {
+        return ref_;
+      }
+      /**
+       * <code>optional int32 ref = 1;</code>
+       */
+      public Builder setRef(int value) {
+        bitField0_ |= 0x00000001;
+        ref_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 ref = 1;</code>
+       */
+      public Builder clearRef() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        ref_ = 0;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object path_ = "";
+      /**
+       * <code>optional string path = 2;</code>
+       */
+      public boolean hasPath() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>optional string path = 2;</code>
+       */
+      public java.lang.String getPath() {
+        java.lang.Object ref = path_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            path_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string path = 2;</code>
+       */
+      public com.google.protobuf.ByteString
+          getPathBytes() {
+        java.lang.Object ref = path_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          path_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string path = 2;</code>
+       */
+      public Builder setPath(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        path_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string path = 2;</code>
+       */
+      public Builder clearPath() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        path_ = getDefaultInstance().getPath();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string path = 2;</code>
+       */
+      public Builder setPathBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        path_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object name_ = "";
+      /**
+       * <code>optional string name = 3;</code>
+       */
+      public boolean hasName() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional string name = 3;</code>
+       */
+      public java.lang.String getName() {
+        java.lang.Object ref = name_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            name_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string name = 3;</code>
+       */
+      public com.google.protobuf.ByteString
+          getNameBytes() {
+        java.lang.Object ref = name_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          name_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string name = 3;</code>
+       */
+      public Builder setName(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        name_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string name = 3;</code>
+       */
+      public Builder clearName() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        name_ = getDefaultInstance().getName();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string name = 3;</code>
+       */
+      public Builder setNameBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        name_ = value;
+        onChanged();
+        return this;
+      }
+
+      private org.sonar.batch.protocol.Constants.ComponentType type_ = org.sonar.batch.protocol.Constants.ComponentType.PROJECT;
+      /**
+       * <code>optional .ComponentType type = 4;</code>
+       */
+      public boolean hasType() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>optional .ComponentType type = 4;</code>
+       */
+      public org.sonar.batch.protocol.Constants.ComponentType getType() {
+        return type_;
+      }
+      /**
+       * <code>optional .ComponentType type = 4;</code>
+       */
+      public Builder setType(org.sonar.batch.protocol.Constants.ComponentType value) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        bitField0_ |= 0x00000008;
+        type_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional .ComponentType type = 4;</code>
+       */
+      public Builder clearType() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        type_ = org.sonar.batch.protocol.Constants.ComponentType.PROJECT;
+        onChanged();
+        return this;
+      }
+
+      private boolean isTest_ ;
+      /**
+       * <code>optional bool is_test = 5;</code>
+       */
+      public boolean hasIsTest() {
+        return ((bitField0_ & 0x00000010) == 0x00000010);
+      }
+      /**
+       * <code>optional bool is_test = 5;</code>
+       */
+      public boolean getIsTest() {
+        return isTest_;
+      }
+      /**
+       * <code>optional bool is_test = 5;</code>
+       */
+      public Builder setIsTest(boolean value) {
+        bitField0_ |= 0x00000010;
+        isTest_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bool is_test = 5;</code>
+       */
+      public Builder clearIsTest() {
+        bitField0_ = (bitField0_ & ~0x00000010);
+        isTest_ = false;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object language_ = "";
+      /**
+       * <code>optional string language = 6;</code>
+       */
+      public boolean hasLanguage() {
+        return ((bitField0_ & 0x00000020) == 0x00000020);
+      }
+      /**
+       * <code>optional string language = 6;</code>
+       */
+      public java.lang.String getLanguage() {
+        java.lang.Object ref = language_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            language_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string language = 6;</code>
+       */
+      public com.google.protobuf.ByteString
+          getLanguageBytes() {
+        java.lang.Object ref = language_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          language_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string language = 6;</code>
+       */
+      public Builder setLanguage(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000020;
+        language_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string language = 6;</code>
+       */
+      public Builder clearLanguage() {
+        bitField0_ = (bitField0_ & ~0x00000020);
+        language_ = getDefaultInstance().getLanguage();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string language = 6;</code>
+       */
+      public Builder setLanguageBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000020;
+        language_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.util.List<java.lang.Integer> childRefs_ = java.util.Collections.emptyList();
+      private void ensureChildRefsIsMutable() {
+        if (!((bitField0_ & 0x00000040) == 0x00000040)) {
+          childRefs_ = new java.util.ArrayList<java.lang.Integer>(childRefs_);
+          bitField0_ |= 0x00000040;
+         }
+      }
+      /**
+       * <code>repeated int32 child_refs = 7;</code>
+       */
+      public java.util.List<java.lang.Integer>
+          getChildRefsList() {
+        return java.util.Collections.unmodifiableList(childRefs_);
+      }
+      /**
+       * <code>repeated int32 child_refs = 7;</code>
+       */
+      public int getChildRefsCount() {
+        return childRefs_.size();
+      }
+      /**
+       * <code>repeated int32 child_refs = 7;</code>
+       */
+      public int getChildRefs(int index) {
+        return childRefs_.get(index);
+      }
+      /**
+       * <code>repeated int32 child_refs = 7;</code>
+       */
+      public Builder setChildRefs(
+          int index, int value) {
+        ensureChildRefsIsMutable();
+        childRefs_.set(index, value);
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>repeated int32 child_refs = 7;</code>
+       */
+      public Builder addChildRefs(int value) {
+        ensureChildRefsIsMutable();
+        childRefs_.add(value);
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>repeated int32 child_refs = 7;</code>
+       */
+      public Builder addAllChildRefs(
+          java.lang.Iterable<? extends java.lang.Integer> values) {
+        ensureChildRefsIsMutable();
+        com.google.protobuf.AbstractMessageLite.Builder.addAll(
+            values, childRefs_);
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>repeated int32 child_refs = 7;</code>
+       */
+      public Builder clearChildRefs() {
+        childRefs_ = java.util.Collections.emptyList();
+        bitField0_ = (bitField0_ & ~0x00000040);
+        onChanged();
+        return this;
+      }
+
+      private int snapshotId_ ;
+      /**
+       * <code>optional int32 snapshot_id = 8;</code>
+       *
+       * <pre>
+       * temporary fields during development of computation stack
+       * </pre>
+       */
+      public boolean hasSnapshotId() {
+        return ((bitField0_ & 0x00000080) == 0x00000080);
+      }
+      /**
+       * <code>optional int32 snapshot_id = 8;</code>
+       *
+       * <pre>
+       * temporary fields during development of computation stack
+       * </pre>
+       */
+      public int getSnapshotId() {
+        return snapshotId_;
+      }
+      /**
+       * <code>optional int32 snapshot_id = 8;</code>
+       *
+       * <pre>
+       * temporary fields during development of computation stack
+       * </pre>
+       */
+      public Builder setSnapshotId(int value) {
+        bitField0_ |= 0x00000080;
+        snapshotId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 snapshot_id = 8;</code>
+       *
+       * <pre>
+       * temporary fields during development of computation stack
+       * </pre>
+       */
+      public Builder clearSnapshotId() {
+        bitField0_ = (bitField0_ & ~0x00000080);
+        snapshotId_ = 0;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object uuid_ = "";
+      /**
+       * <code>optional string uuid = 9;</code>
+       */
+      public boolean hasUuid() {
+        return ((bitField0_ & 0x00000100) == 0x00000100);
+      }
+      /**
+       * <code>optional string uuid = 9;</code>
+       */
+      public java.lang.String getUuid() {
+        java.lang.Object ref = uuid_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            uuid_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string uuid = 9;</code>
+       */
+      public com.google.protobuf.ByteString
+          getUuidBytes() {
+        java.lang.Object ref = uuid_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          uuid_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string uuid = 9;</code>
+       */
+      public Builder setUuid(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000100;
+        uuid_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string uuid = 9;</code>
+       */
+      public Builder clearUuid() {
+        bitField0_ = (bitField0_ & ~0x00000100);
+        uuid_ = getDefaultInstance().getUuid();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string uuid = 9;</code>
+       */
+      public Builder setUuidBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000100;
+        uuid_ = value;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:ReportComponent)
+    }
+
+    static {
+      defaultInstance = new ReportComponent(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:ReportComponent)
+  }
+
+  public interface ReportIssueOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:ReportIssue)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>optional string rule_repository = 1;</code>
+     */
+    boolean hasRuleRepository();
+    /**
+     * <code>optional string rule_repository = 1;</code>
+     */
+    java.lang.String getRuleRepository();
+    /**
+     * <code>optional string rule_repository = 1;</code>
+     */
+    com.google.protobuf.ByteString
+        getRuleRepositoryBytes();
+
+    /**
+     * <code>optional string rule_key = 2;</code>
+     */
+    boolean hasRuleKey();
+    /**
+     * <code>optional string rule_key = 2;</code>
+     */
+    java.lang.String getRuleKey();
+    /**
+     * <code>optional string rule_key = 2;</code>
+     */
+    com.google.protobuf.ByteString
+        getRuleKeyBytes();
+
+    /**
+     * <code>optional int32 line = 3;</code>
+     */
+    boolean hasLine();
+    /**
+     * <code>optional int32 line = 3;</code>
+     */
+    int getLine();
+
+    /**
+     * <code>optional string msg = 4;</code>
+     */
+    boolean hasMsg();
+    /**
+     * <code>optional string msg = 4;</code>
+     */
+    java.lang.String getMsg();
+    /**
+     * <code>optional string msg = 4;</code>
+     */
+    com.google.protobuf.ByteString
+        getMsgBytes();
+
+    /**
+     * <code>optional .Severity severity = 5;</code>
+     */
+    boolean hasSeverity();
+    /**
+     * <code>optional .Severity severity = 5;</code>
+     */
+    org.sonar.batch.protocol.Constants.Severity getSeverity();
+
+    /**
+     * <code>repeated string tags = 6;</code>
+     */
+    com.google.protobuf.ProtocolStringList
+        getTagsList();
+    /**
+     * <code>repeated string tags = 6;</code>
+     */
+    int getTagsCount();
+    /**
+     * <code>repeated string tags = 6;</code>
+     */
+    java.lang.String getTags(int index);
+    /**
+     * <code>repeated string tags = 6;</code>
+     */
+    com.google.protobuf.ByteString
+        getTagsBytes(int index);
+
+    /**
+     * <code>optional double effort_to_fix = 7;</code>
+     *
+     * <pre>
+     * temporary fields during development of computation stack
+     * </pre>
+     */
+    boolean hasEffortToFix();
+    /**
+     * <code>optional double effort_to_fix = 7;</code>
+     *
+     * <pre>
+     * temporary fields during development of computation stack
+     * </pre>
+     */
+    double getEffortToFix();
+
+    /**
+     * <code>optional bool is_new = 8;</code>
+     */
+    boolean hasIsNew();
+    /**
+     * <code>optional bool is_new = 8;</code>
+     */
+    boolean getIsNew();
+
+    /**
+     * <code>optional string uuid = 9;</code>
+     */
+    boolean hasUuid();
+    /**
+     * <code>optional string uuid = 9;</code>
+     */
+    java.lang.String getUuid();
+    /**
+     * <code>optional string uuid = 9;</code>
+     */
+    com.google.protobuf.ByteString
+        getUuidBytes();
+
+    /**
+     * <code>optional int64 debt_in_minutes = 10;</code>
+     */
+    boolean hasDebtInMinutes();
+    /**
+     * <code>optional int64 debt_in_minutes = 10;</code>
+     */
+    long getDebtInMinutes();
+
+    /**
+     * <code>optional string resolution = 11;</code>
+     */
+    boolean hasResolution();
+    /**
+     * <code>optional string resolution = 11;</code>
+     */
+    java.lang.String getResolution();
+    /**
+     * <code>optional string resolution = 11;</code>
+     */
+    com.google.protobuf.ByteString
+        getResolutionBytes();
+
+    /**
+     * <code>optional string status = 12;</code>
+     */
+    boolean hasStatus();
+    /**
+     * <code>optional string status = 12;</code>
+     */
+    java.lang.String getStatus();
+    /**
+     * <code>optional string status = 12;</code>
+     */
+    com.google.protobuf.ByteString
+        getStatusBytes();
+
+    /**
+     * <code>optional string checksum = 13;</code>
+     */
+    boolean hasChecksum();
+    /**
+     * <code>optional string checksum = 13;</code>
+     */
+    java.lang.String getChecksum();
+    /**
+     * <code>optional string checksum = 13;</code>
+     */
+    com.google.protobuf.ByteString
+        getChecksumBytes();
+
+    /**
+     * <code>optional bool manual_severity = 14;</code>
+     */
+    boolean hasManualSeverity();
+    /**
+     * <code>optional bool manual_severity = 14;</code>
+     */
+    boolean getManualSeverity();
+
+    /**
+     * <code>optional string reporter = 15;</code>
+     */
+    boolean hasReporter();
+    /**
+     * <code>optional string reporter = 15;</code>
+     */
+    java.lang.String getReporter();
+    /**
+     * <code>optional string reporter = 15;</code>
+     */
+    com.google.protobuf.ByteString
+        getReporterBytes();
+
+    /**
+     * <code>optional string assignee = 16;</code>
+     */
+    boolean hasAssignee();
+    /**
+     * <code>optional string assignee = 16;</code>
+     */
+    java.lang.String getAssignee();
+    /**
+     * <code>optional string assignee = 16;</code>
+     */
+    com.google.protobuf.ByteString
+        getAssigneeBytes();
+
+    /**
+     * <code>optional string action_plan_key = 17;</code>
+     */
+    boolean hasActionPlanKey();
+    /**
+     * <code>optional string action_plan_key = 17;</code>
+     */
+    java.lang.String getActionPlanKey();
+    /**
+     * <code>optional string action_plan_key = 17;</code>
+     */
+    com.google.protobuf.ByteString
+        getActionPlanKeyBytes();
+
+    /**
+     * <code>optional string attributes = 18;</code>
+     */
+    boolean hasAttributes();
+    /**
+     * <code>optional string attributes = 18;</code>
+     */
+    java.lang.String getAttributes();
+    /**
+     * <code>optional string attributes = 18;</code>
+     */
+    com.google.protobuf.ByteString
+        getAttributesBytes();
+
+    /**
+     * <code>optional string author_login = 19;</code>
+     */
+    boolean hasAuthorLogin();
+    /**
+     * <code>optional string author_login = 19;</code>
+     */
+    java.lang.String getAuthorLogin();
+    /**
+     * <code>optional string author_login = 19;</code>
+     */
+    com.google.protobuf.ByteString
+        getAuthorLoginBytes();
+
+    /**
+     * <code>optional int64 creation_date = 20;</code>
+     */
+    boolean hasCreationDate();
+    /**
+     * <code>optional int64 creation_date = 20;</code>
+     */
+    long getCreationDate();
+
+    /**
+     * <code>optional int64 close_date = 21;</code>
+     */
+    boolean hasCloseDate();
+    /**
+     * <code>optional int64 close_date = 21;</code>
+     */
+    long getCloseDate();
+
+    /**
+     * <code>optional int64 update_date = 22;</code>
+     */
+    boolean hasUpdateDate();
+    /**
+     * <code>optional int64 update_date = 22;</code>
+     */
+    long getUpdateDate();
+
+    /**
+     * <code>optional int64 selected_at = 23;</code>
+     */
+    boolean hasSelectedAt();
+    /**
+     * <code>optional int64 selected_at = 23;</code>
+     */
+    long getSelectedAt();
+
+    /**
+     * <code>optional string diff_fields = 24;</code>
+     */
+    boolean hasDiffFields();
+    /**
+     * <code>optional string diff_fields = 24;</code>
+     */
+    java.lang.String getDiffFields();
+    /**
+     * <code>optional string diff_fields = 24;</code>
+     */
+    com.google.protobuf.ByteString
+        getDiffFieldsBytes();
+
+    /**
+     * <code>optional bool is_changed = 25;</code>
+     */
+    boolean hasIsChanged();
+    /**
+     * <code>optional bool is_changed = 25;</code>
+     */
+    boolean getIsChanged();
+
+    /**
+     * <code>optional bool must_send_notification = 26;</code>
+     */
+    boolean hasMustSendNotification();
+    /**
+     * <code>optional bool must_send_notification = 26;</code>
+     */
+    boolean getMustSendNotification();
+  }
+  /**
+   * Protobuf type {@code ReportIssue}
+   */
+  public static final class ReportIssue extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:ReportIssue)
+      ReportIssueOrBuilder {
+    // Use ReportIssue.newBuilder() to construct.
+    private ReportIssue(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private ReportIssue(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final ReportIssue defaultInstance;
+    public static ReportIssue getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public ReportIssue getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private ReportIssue(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000001;
+              ruleRepository_ = bs;
+              break;
+            }
+            case 18: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000002;
+              ruleKey_ = bs;
+              break;
+            }
+            case 24: {
+              bitField0_ |= 0x00000004;
+              line_ = input.readInt32();
+              break;
+            }
+            case 34: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000008;
+              msg_ = bs;
+              break;
+            }
+            case 40: {
+              int rawValue = input.readEnum();
+              org.sonar.batch.protocol.Constants.Severity value = org.sonar.batch.protocol.Constants.Severity.valueOf(rawValue);
+              if (value == null) {
+                unknownFields.mergeVarintField(5, rawValue);
+              } else {
+                bitField0_ |= 0x00000010;
+                severity_ = value;
+              }
+              break;
+            }
+            case 50: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              if (!((mutable_bitField0_ & 0x00000020) == 0x00000020)) {
+                tags_ = new com.google.protobuf.LazyStringArrayList();
+                mutable_bitField0_ |= 0x00000020;
+              }
+              tags_.add(bs);
+              break;
+            }
+            case 57: {
+              bitField0_ |= 0x00000020;
+              effortToFix_ = input.readDouble();
+              break;
+            }
+            case 64: {
+              bitField0_ |= 0x00000040;
+              isNew_ = input.readBool();
+              break;
+            }
+            case 74: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000080;
+              uuid_ = bs;
+              break;
+            }
+            case 80: {
+              bitField0_ |= 0x00000100;
+              debtInMinutes_ = input.readInt64();
+              break;
+            }
+            case 90: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000200;
+              resolution_ = bs;
+              break;
+            }
+            case 98: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000400;
+              status_ = bs;
+              break;
+            }
+            case 106: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00000800;
+              checksum_ = bs;
+              break;
+            }
+            case 112: {
+              bitField0_ |= 0x00001000;
+              manualSeverity_ = input.readBool();
+              break;
+            }
+            case 122: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00002000;
+              reporter_ = bs;
+              break;
+            }
+            case 130: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00004000;
+              assignee_ = bs;
+              break;
+            }
+            case 138: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00008000;
+              actionPlanKey_ = bs;
+              break;
+            }
+            case 146: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00010000;
+              attributes_ = bs;
+              break;
+            }
+            case 154: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00020000;
+              authorLogin_ = bs;
+              break;
+            }
+            case 160: {
+              bitField0_ |= 0x00040000;
+              creationDate_ = input.readInt64();
+              break;
+            }
+            case 168: {
+              bitField0_ |= 0x00080000;
+              closeDate_ = input.readInt64();
+              break;
+            }
+            case 176: {
+              bitField0_ |= 0x00100000;
+              updateDate_ = input.readInt64();
+              break;
+            }
+            case 184: {
+              bitField0_ |= 0x00200000;
+              selectedAt_ = input.readInt64();
+              break;
+            }
+            case 194: {
+              com.google.protobuf.ByteString bs = input.readBytes();
+              bitField0_ |= 0x00400000;
+              diffFields_ = bs;
+              break;
+            }
+            case 200: {
+              bitField0_ |= 0x00800000;
+              isChanged_ = input.readBool();
+              break;
+            }
+            case 208: {
+              bitField0_ |= 0x01000000;
+              mustSendNotification_ = input.readBool();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        if (((mutable_bitField0_ & 0x00000020) == 0x00000020)) {
+          tags_ = tags_.getUnmodifiableView();
+        }
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportIssue_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportIssue_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.sonar.batch.protocol.output.BatchOutput.ReportIssue.class, org.sonar.batch.protocol.output.BatchOutput.ReportIssue.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<ReportIssue> PARSER =
+        new com.google.protobuf.AbstractParser<ReportIssue>() {
+      public ReportIssue parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new ReportIssue(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<ReportIssue> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    public static final int RULE_REPOSITORY_FIELD_NUMBER = 1;
+    private java.lang.Object ruleRepository_;
+    /**
+     * <code>optional string rule_repository = 1;</code>
+     */
+    public boolean hasRuleRepository() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>optional string rule_repository = 1;</code>
+     */
+    public java.lang.String getRuleRepository() {
+      java.lang.Object ref = ruleRepository_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          ruleRepository_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string rule_repository = 1;</code>
+     */
+    public com.google.protobuf.ByteString
+        getRuleRepositoryBytes() {
+      java.lang.Object ref = ruleRepository_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        ruleRepository_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int RULE_KEY_FIELD_NUMBER = 2;
+    private java.lang.Object ruleKey_;
+    /**
+     * <code>optional string rule_key = 2;</code>
+     */
+    public boolean hasRuleKey() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>optional string rule_key = 2;</code>
+     */
+    public java.lang.String getRuleKey() {
+      java.lang.Object ref = ruleKey_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          ruleKey_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string rule_key = 2;</code>
+     */
+    public com.google.protobuf.ByteString
+        getRuleKeyBytes() {
+      java.lang.Object ref = ruleKey_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        ruleKey_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int LINE_FIELD_NUMBER = 3;
+    private int line_;
+    /**
+     * <code>optional int32 line = 3;</code>
+     */
+    public boolean hasLine() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional int32 line = 3;</code>
+     */
+    public int getLine() {
+      return line_;
+    }
+
+    public static final int MSG_FIELD_NUMBER = 4;
+    private java.lang.Object msg_;
+    /**
+     * <code>optional string msg = 4;</code>
+     */
+    public boolean hasMsg() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>optional string msg = 4;</code>
+     */
+    public java.lang.String getMsg() {
+      java.lang.Object ref = msg_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          msg_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string msg = 4;</code>
+     */
+    public com.google.protobuf.ByteString
+        getMsgBytes() {
+      java.lang.Object ref = msg_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        msg_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int SEVERITY_FIELD_NUMBER = 5;
+    private org.sonar.batch.protocol.Constants.Severity severity_;
+    /**
+     * <code>optional .Severity severity = 5;</code>
+     */
+    public boolean hasSeverity() {
+      return ((bitField0_ & 0x00000010) == 0x00000010);
+    }
+    /**
+     * <code>optional .Severity severity = 5;</code>
+     */
+    public org.sonar.batch.protocol.Constants.Severity getSeverity() {
+      return severity_;
+    }
+
+    public static final int TAGS_FIELD_NUMBER = 6;
+    private com.google.protobuf.LazyStringList tags_;
+    /**
+     * <code>repeated string tags = 6;</code>
+     */
+    public com.google.protobuf.ProtocolStringList
+        getTagsList() {
+      return tags_;
+    }
+    /**
+     * <code>repeated string tags = 6;</code>
+     */
+    public int getTagsCount() {
+      return tags_.size();
+    }
+    /**
+     * <code>repeated string tags = 6;</code>
+     */
+    public java.lang.String getTags(int index) {
+      return tags_.get(index);
+    }
+    /**
+     * <code>repeated string tags = 6;</code>
+     */
+    public com.google.protobuf.ByteString
+        getTagsBytes(int index) {
+      return tags_.getByteString(index);
+    }
+
+    public static final int EFFORT_TO_FIX_FIELD_NUMBER = 7;
+    private double effortToFix_;
+    /**
+     * <code>optional double effort_to_fix = 7;</code>
+     *
+     * <pre>
+     * temporary fields during development of computation stack
+     * </pre>
+     */
+    public boolean hasEffortToFix() {
+      return ((bitField0_ & 0x00000020) == 0x00000020);
+    }
+    /**
+     * <code>optional double effort_to_fix = 7;</code>
+     *
+     * <pre>
+     * temporary fields during development of computation stack
+     * </pre>
+     */
+    public double getEffortToFix() {
+      return effortToFix_;
+    }
+
+    public static final int IS_NEW_FIELD_NUMBER = 8;
+    private boolean isNew_;
+    /**
+     * <code>optional bool is_new = 8;</code>
+     */
+    public boolean hasIsNew() {
+      return ((bitField0_ & 0x00000040) == 0x00000040);
+    }
+    /**
+     * <code>optional bool is_new = 8;</code>
+     */
+    public boolean getIsNew() {
+      return isNew_;
+    }
+
+    public static final int UUID_FIELD_NUMBER = 9;
+    private java.lang.Object uuid_;
+    /**
+     * <code>optional string uuid = 9;</code>
+     */
+    public boolean hasUuid() {
+      return ((bitField0_ & 0x00000080) == 0x00000080);
+    }
+    /**
+     * <code>optional string uuid = 9;</code>
+     */
+    public java.lang.String getUuid() {
+      java.lang.Object ref = uuid_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          uuid_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string uuid = 9;</code>
+     */
+    public com.google.protobuf.ByteString
+        getUuidBytes() {
+      java.lang.Object ref = uuid_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        uuid_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int DEBT_IN_MINUTES_FIELD_NUMBER = 10;
+    private long debtInMinutes_;
+    /**
+     * <code>optional int64 debt_in_minutes = 10;</code>
+     */
+    public boolean hasDebtInMinutes() {
+      return ((bitField0_ & 0x00000100) == 0x00000100);
+    }
+    /**
+     * <code>optional int64 debt_in_minutes = 10;</code>
+     */
+    public long getDebtInMinutes() {
+      return debtInMinutes_;
+    }
+
+    public static final int RESOLUTION_FIELD_NUMBER = 11;
+    private java.lang.Object resolution_;
+    /**
+     * <code>optional string resolution = 11;</code>
+     */
+    public boolean hasResolution() {
+      return ((bitField0_ & 0x00000200) == 0x00000200);
+    }
+    /**
+     * <code>optional string resolution = 11;</code>
+     */
+    public java.lang.String getResolution() {
+      java.lang.Object ref = resolution_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          resolution_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string resolution = 11;</code>
+     */
+    public com.google.protobuf.ByteString
+        getResolutionBytes() {
+      java.lang.Object ref = resolution_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        resolution_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int STATUS_FIELD_NUMBER = 12;
+    private java.lang.Object status_;
+    /**
+     * <code>optional string status = 12;</code>
+     */
+    public boolean hasStatus() {
+      return ((bitField0_ & 0x00000400) == 0x00000400);
+    }
+    /**
+     * <code>optional string status = 12;</code>
+     */
+    public java.lang.String getStatus() {
+      java.lang.Object ref = status_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          status_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string status = 12;</code>
+     */
+    public com.google.protobuf.ByteString
+        getStatusBytes() {
+      java.lang.Object ref = status_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        status_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int CHECKSUM_FIELD_NUMBER = 13;
+    private java.lang.Object checksum_;
+    /**
+     * <code>optional string checksum = 13;</code>
+     */
+    public boolean hasChecksum() {
+      return ((bitField0_ & 0x00000800) == 0x00000800);
+    }
+    /**
+     * <code>optional string checksum = 13;</code>
+     */
+    public java.lang.String getChecksum() {
+      java.lang.Object ref = checksum_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          checksum_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string checksum = 13;</code>
+     */
+    public com.google.protobuf.ByteString
+        getChecksumBytes() {
+      java.lang.Object ref = checksum_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        checksum_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int MANUAL_SEVERITY_FIELD_NUMBER = 14;
+    private boolean manualSeverity_;
+    /**
+     * <code>optional bool manual_severity = 14;</code>
+     */
+    public boolean hasManualSeverity() {
+      return ((bitField0_ & 0x00001000) == 0x00001000);
+    }
+    /**
+     * <code>optional bool manual_severity = 14;</code>
+     */
+    public boolean getManualSeverity() {
+      return manualSeverity_;
+    }
+
+    public static final int REPORTER_FIELD_NUMBER = 15;
+    private java.lang.Object reporter_;
+    /**
+     * <code>optional string reporter = 15;</code>
+     */
+    public boolean hasReporter() {
+      return ((bitField0_ & 0x00002000) == 0x00002000);
+    }
+    /**
+     * <code>optional string reporter = 15;</code>
+     */
+    public java.lang.String getReporter() {
+      java.lang.Object ref = reporter_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          reporter_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string reporter = 15;</code>
+     */
+    public com.google.protobuf.ByteString
+        getReporterBytes() {
+      java.lang.Object ref = reporter_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        reporter_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int ASSIGNEE_FIELD_NUMBER = 16;
+    private java.lang.Object assignee_;
+    /**
+     * <code>optional string assignee = 16;</code>
+     */
+    public boolean hasAssignee() {
+      return ((bitField0_ & 0x00004000) == 0x00004000);
+    }
+    /**
+     * <code>optional string assignee = 16;</code>
+     */
+    public java.lang.String getAssignee() {
+      java.lang.Object ref = assignee_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          assignee_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string assignee = 16;</code>
+     */
+    public com.google.protobuf.ByteString
+        getAssigneeBytes() {
+      java.lang.Object ref = assignee_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        assignee_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int ACTION_PLAN_KEY_FIELD_NUMBER = 17;
+    private java.lang.Object actionPlanKey_;
+    /**
+     * <code>optional string action_plan_key = 17;</code>
+     */
+    public boolean hasActionPlanKey() {
+      return ((bitField0_ & 0x00008000) == 0x00008000);
+    }
+    /**
+     * <code>optional string action_plan_key = 17;</code>
+     */
+    public java.lang.String getActionPlanKey() {
+      java.lang.Object ref = actionPlanKey_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          actionPlanKey_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string action_plan_key = 17;</code>
+     */
+    public com.google.protobuf.ByteString
+        getActionPlanKeyBytes() {
+      java.lang.Object ref = actionPlanKey_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        actionPlanKey_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int ATTRIBUTES_FIELD_NUMBER = 18;
+    private java.lang.Object attributes_;
+    /**
+     * <code>optional string attributes = 18;</code>
+     */
+    public boolean hasAttributes() {
+      return ((bitField0_ & 0x00010000) == 0x00010000);
+    }
+    /**
+     * <code>optional string attributes = 18;</code>
+     */
+    public java.lang.String getAttributes() {
+      java.lang.Object ref = attributes_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          attributes_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string attributes = 18;</code>
+     */
+    public com.google.protobuf.ByteString
+        getAttributesBytes() {
+      java.lang.Object ref = attributes_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        attributes_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int AUTHOR_LOGIN_FIELD_NUMBER = 19;
+    private java.lang.Object authorLogin_;
+    /**
+     * <code>optional string author_login = 19;</code>
+     */
+    public boolean hasAuthorLogin() {
+      return ((bitField0_ & 0x00020000) == 0x00020000);
+    }
+    /**
+     * <code>optional string author_login = 19;</code>
+     */
+    public java.lang.String getAuthorLogin() {
+      java.lang.Object ref = authorLogin_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          authorLogin_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string author_login = 19;</code>
+     */
+    public com.google.protobuf.ByteString
+        getAuthorLoginBytes() {
+      java.lang.Object ref = authorLogin_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        authorLogin_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int CREATION_DATE_FIELD_NUMBER = 20;
+    private long creationDate_;
+    /**
+     * <code>optional int64 creation_date = 20;</code>
+     */
+    public boolean hasCreationDate() {
+      return ((bitField0_ & 0x00040000) == 0x00040000);
+    }
+    /**
+     * <code>optional int64 creation_date = 20;</code>
+     */
+    public long getCreationDate() {
+      return creationDate_;
+    }
+
+    public static final int CLOSE_DATE_FIELD_NUMBER = 21;
+    private long closeDate_;
+    /**
+     * <code>optional int64 close_date = 21;</code>
+     */
+    public boolean hasCloseDate() {
+      return ((bitField0_ & 0x00080000) == 0x00080000);
+    }
+    /**
+     * <code>optional int64 close_date = 21;</code>
+     */
+    public long getCloseDate() {
+      return closeDate_;
+    }
+
+    public static final int UPDATE_DATE_FIELD_NUMBER = 22;
+    private long updateDate_;
+    /**
+     * <code>optional int64 update_date = 22;</code>
+     */
+    public boolean hasUpdateDate() {
+      return ((bitField0_ & 0x00100000) == 0x00100000);
+    }
+    /**
+     * <code>optional int64 update_date = 22;</code>
+     */
+    public long getUpdateDate() {
+      return updateDate_;
+    }
+
+    public static final int SELECTED_AT_FIELD_NUMBER = 23;
+    private long selectedAt_;
+    /**
+     * <code>optional int64 selected_at = 23;</code>
+     */
+    public boolean hasSelectedAt() {
+      return ((bitField0_ & 0x00200000) == 0x00200000);
+    }
+    /**
+     * <code>optional int64 selected_at = 23;</code>
+     */
+    public long getSelectedAt() {
+      return selectedAt_;
+    }
+
+    public static final int DIFF_FIELDS_FIELD_NUMBER = 24;
+    private java.lang.Object diffFields_;
+    /**
+     * <code>optional string diff_fields = 24;</code>
+     */
+    public boolean hasDiffFields() {
+      return ((bitField0_ & 0x00400000) == 0x00400000);
+    }
+    /**
+     * <code>optional string diff_fields = 24;</code>
+     */
+    public java.lang.String getDiffFields() {
+      java.lang.Object ref = diffFields_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          diffFields_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string diff_fields = 24;</code>
+     */
+    public com.google.protobuf.ByteString
+        getDiffFieldsBytes() {
+      java.lang.Object ref = diffFields_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        diffFields_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    public static final int IS_CHANGED_FIELD_NUMBER = 25;
+    private boolean isChanged_;
+    /**
+     * <code>optional bool is_changed = 25;</code>
+     */
+    public boolean hasIsChanged() {
+      return ((bitField0_ & 0x00800000) == 0x00800000);
+    }
+    /**
+     * <code>optional bool is_changed = 25;</code>
+     */
+    public boolean getIsChanged() {
+      return isChanged_;
+    }
+
+    public static final int MUST_SEND_NOTIFICATION_FIELD_NUMBER = 26;
+    private boolean mustSendNotification_;
+    /**
+     * <code>optional bool must_send_notification = 26;</code>
+     */
+    public boolean hasMustSendNotification() {
+      return ((bitField0_ & 0x01000000) == 0x01000000);
+    }
+    /**
+     * <code>optional bool must_send_notification = 26;</code>
+     */
+    public boolean getMustSendNotification() {
+      return mustSendNotification_;
+    }
+
+    private void initFields() {
+      ruleRepository_ = "";
+      ruleKey_ = "";
+      line_ = 0;
+      msg_ = "";
+      severity_ = org.sonar.batch.protocol.Constants.Severity.INFO;
+      tags_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+      effortToFix_ = 0D;
+      isNew_ = false;
+      uuid_ = "";
+      debtInMinutes_ = 0L;
+      resolution_ = "";
+      status_ = "";
+      checksum_ = "";
+      manualSeverity_ = false;
+      reporter_ = "";
+      assignee_ = "";
+      actionPlanKey_ = "";
+      attributes_ = "";
+      authorLogin_ = "";
+      creationDate_ = 0L;
+      closeDate_ = 0L;
+      updateDate_ = 0L;
+      selectedAt_ = 0L;
+      diffFields_ = "";
+      isChanged_ = false;
+      mustSendNotification_ = false;
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeBytes(1, getRuleRepositoryBytes());
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeBytes(2, getRuleKeyBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeInt32(3, line_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeBytes(4, getMsgBytes());
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        output.writeEnum(5, severity_.getNumber());
+      }
+      for (int i = 0; i < tags_.size(); i++) {
+        output.writeBytes(6, tags_.getByteString(i));
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        output.writeDouble(7, effortToFix_);
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        output.writeBool(8, isNew_);
+      }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        output.writeBytes(9, getUuidBytes());
+      }
+      if (((bitField0_ & 0x00000100) == 0x00000100)) {
+        output.writeInt64(10, debtInMinutes_);
+      }
+      if (((bitField0_ & 0x00000200) == 0x00000200)) {
+        output.writeBytes(11, getResolutionBytes());
+      }
+      if (((bitField0_ & 0x00000400) == 0x00000400)) {
+        output.writeBytes(12, getStatusBytes());
+      }
+      if (((bitField0_ & 0x00000800) == 0x00000800)) {
+        output.writeBytes(13, getChecksumBytes());
+      }
+      if (((bitField0_ & 0x00001000) == 0x00001000)) {
+        output.writeBool(14, manualSeverity_);
+      }
+      if (((bitField0_ & 0x00002000) == 0x00002000)) {
+        output.writeBytes(15, getReporterBytes());
+      }
+      if (((bitField0_ & 0x00004000) == 0x00004000)) {
+        output.writeBytes(16, getAssigneeBytes());
+      }
+      if (((bitField0_ & 0x00008000) == 0x00008000)) {
+        output.writeBytes(17, getActionPlanKeyBytes());
+      }
+      if (((bitField0_ & 0x00010000) == 0x00010000)) {
+        output.writeBytes(18, getAttributesBytes());
+      }
+      if (((bitField0_ & 0x00020000) == 0x00020000)) {
+        output.writeBytes(19, getAuthorLoginBytes());
+      }
+      if (((bitField0_ & 0x00040000) == 0x00040000)) {
+        output.writeInt64(20, creationDate_);
+      }
+      if (((bitField0_ & 0x00080000) == 0x00080000)) {
+        output.writeInt64(21, closeDate_);
+      }
+      if (((bitField0_ & 0x00100000) == 0x00100000)) {
+        output.writeInt64(22, updateDate_);
+      }
+      if (((bitField0_ & 0x00200000) == 0x00200000)) {
+        output.writeInt64(23, selectedAt_);
+      }
+      if (((bitField0_ & 0x00400000) == 0x00400000)) {
+        output.writeBytes(24, getDiffFieldsBytes());
+      }
+      if (((bitField0_ & 0x00800000) == 0x00800000)) {
+        output.writeBool(25, isChanged_);
+      }
+      if (((bitField0_ & 0x01000000) == 0x01000000)) {
+        output.writeBool(26, mustSendNotification_);
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(1, getRuleRepositoryBytes());
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(2, getRuleKeyBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(3, line_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(4, getMsgBytes());
+      }
+      if (((bitField0_ & 0x00000010) == 0x00000010)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeEnumSize(5, severity_.getNumber());
+      }
+      {
+        int dataSize = 0;
+        for (int i = 0; i < tags_.size(); i++) {
+          dataSize += com.google.protobuf.CodedOutputStream
+            .computeBytesSizeNoTag(tags_.getByteString(i));
+        }
+        size += dataSize;
+        size += 1 * getTagsList().size();
+      }
+      if (((bitField0_ & 0x00000020) == 0x00000020)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeDoubleSize(7, effortToFix_);
+      }
+      if (((bitField0_ & 0x00000040) == 0x00000040)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBoolSize(8, isNew_);
+      }
+      if (((bitField0_ & 0x00000080) == 0x00000080)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(9, getUuidBytes());
+      }
+      if (((bitField0_ & 0x00000100) == 0x00000100)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(10, debtInMinutes_);
+      }
+      if (((bitField0_ & 0x00000200) == 0x00000200)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(11, getResolutionBytes());
+      }
+      if (((bitField0_ & 0x00000400) == 0x00000400)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(12, getStatusBytes());
+      }
+      if (((bitField0_ & 0x00000800) == 0x00000800)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(13, getChecksumBytes());
+      }
+      if (((bitField0_ & 0x00001000) == 0x00001000)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBoolSize(14, manualSeverity_);
+      }
+      if (((bitField0_ & 0x00002000) == 0x00002000)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(15, getReporterBytes());
+      }
+      if (((bitField0_ & 0x00004000) == 0x00004000)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(16, getAssigneeBytes());
+      }
+      if (((bitField0_ & 0x00008000) == 0x00008000)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(17, getActionPlanKeyBytes());
+      }
+      if (((bitField0_ & 0x00010000) == 0x00010000)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(18, getAttributesBytes());
+      }
+      if (((bitField0_ & 0x00020000) == 0x00020000)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(19, getAuthorLoginBytes());
+      }
+      if (((bitField0_ & 0x00040000) == 0x00040000)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(20, creationDate_);
+      }
+      if (((bitField0_ & 0x00080000) == 0x00080000)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(21, closeDate_);
+      }
+      if (((bitField0_ & 0x00100000) == 0x00100000)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(22, updateDate_);
+      }
+      if (((bitField0_ & 0x00200000) == 0x00200000)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(23, selectedAt_);
+      }
+      if (((bitField0_ & 0x00400000) == 0x00400000)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(24, getDiffFieldsBytes());
+      }
+      if (((bitField0_ & 0x00800000) == 0x00800000)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBoolSize(25, isChanged_);
+      }
+      if (((bitField0_ & 0x01000000) == 0x01000000)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBoolSize(26, mustSendNotification_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssue parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssue parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssue parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssue parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssue parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssue parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssue parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssue parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssue parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssue parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.sonar.batch.protocol.output.BatchOutput.ReportIssue prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code ReportIssue}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:ReportIssue)
+        org.sonar.batch.protocol.output.BatchOutput.ReportIssueOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportIssue_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportIssue_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.sonar.batch.protocol.output.BatchOutput.ReportIssue.class, org.sonar.batch.protocol.output.BatchOutput.ReportIssue.Builder.class);
+      }
+
+      // Construct using org.sonar.batch.protocol.output.BatchOutput.ReportIssue.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        ruleRepository_ = "";
+        bitField0_ = (bitField0_ & ~0x00000001);
+        ruleKey_ = "";
+        bitField0_ = (bitField0_ & ~0x00000002);
+        line_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000004);
+        msg_ = "";
+        bitField0_ = (bitField0_ & ~0x00000008);
+        severity_ = org.sonar.batch.protocol.Constants.Severity.INFO;
+        bitField0_ = (bitField0_ & ~0x00000010);
+        tags_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000020);
+        effortToFix_ = 0D;
+        bitField0_ = (bitField0_ & ~0x00000040);
+        isNew_ = false;
+        bitField0_ = (bitField0_ & ~0x00000080);
+        uuid_ = "";
+        bitField0_ = (bitField0_ & ~0x00000100);
+        debtInMinutes_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000200);
+        resolution_ = "";
+        bitField0_ = (bitField0_ & ~0x00000400);
+        status_ = "";
+        bitField0_ = (bitField0_ & ~0x00000800);
+        checksum_ = "";
+        bitField0_ = (bitField0_ & ~0x00001000);
+        manualSeverity_ = false;
+        bitField0_ = (bitField0_ & ~0x00002000);
+        reporter_ = "";
+        bitField0_ = (bitField0_ & ~0x00004000);
+        assignee_ = "";
+        bitField0_ = (bitField0_ & ~0x00008000);
+        actionPlanKey_ = "";
+        bitField0_ = (bitField0_ & ~0x00010000);
+        attributes_ = "";
+        bitField0_ = (bitField0_ & ~0x00020000);
+        authorLogin_ = "";
+        bitField0_ = (bitField0_ & ~0x00040000);
+        creationDate_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00080000);
+        closeDate_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00100000);
+        updateDate_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00200000);
+        selectedAt_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00400000);
+        diffFields_ = "";
+        bitField0_ = (bitField0_ & ~0x00800000);
+        isChanged_ = false;
+        bitField0_ = (bitField0_ & ~0x01000000);
+        mustSendNotification_ = false;
+        bitField0_ = (bitField0_ & ~0x02000000);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportIssue_descriptor;
+      }
+
+      public org.sonar.batch.protocol.output.BatchOutput.ReportIssue getDefaultInstanceForType() {
+        return org.sonar.batch.protocol.output.BatchOutput.ReportIssue.getDefaultInstance();
+      }
+
+      public org.sonar.batch.protocol.output.BatchOutput.ReportIssue build() {
+        org.sonar.batch.protocol.output.BatchOutput.ReportIssue result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.sonar.batch.protocol.output.BatchOutput.ReportIssue buildPartial() {
+        org.sonar.batch.protocol.output.BatchOutput.ReportIssue result = new org.sonar.batch.protocol.output.BatchOutput.ReportIssue(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.ruleRepository_ = ruleRepository_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.ruleKey_ = ruleKey_;
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.line_ = line_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.msg_ = msg_;
+        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+          to_bitField0_ |= 0x00000010;
+        }
+        result.severity_ = severity_;
+        if (((bitField0_ & 0x00000020) == 0x00000020)) {
+          tags_ = tags_.getUnmodifiableView();
+          bitField0_ = (bitField0_ & ~0x00000020);
+        }
+        result.tags_ = tags_;
+        if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
+          to_bitField0_ |= 0x00000020;
+        }
+        result.effortToFix_ = effortToFix_;
+        if (((from_bitField0_ & 0x00000080) == 0x00000080)) {
+          to_bitField0_ |= 0x00000040;
+        }
+        result.isNew_ = isNew_;
+        if (((from_bitField0_ & 0x00000100) == 0x00000100)) {
+          to_bitField0_ |= 0x00000080;
+        }
+        result.uuid_ = uuid_;
+        if (((from_bitField0_ & 0x00000200) == 0x00000200)) {
+          to_bitField0_ |= 0x00000100;
+        }
+        result.debtInMinutes_ = debtInMinutes_;
+        if (((from_bitField0_ & 0x00000400) == 0x00000400)) {
+          to_bitField0_ |= 0x00000200;
+        }
+        result.resolution_ = resolution_;
+        if (((from_bitField0_ & 0x00000800) == 0x00000800)) {
+          to_bitField0_ |= 0x00000400;
+        }
+        result.status_ = status_;
+        if (((from_bitField0_ & 0x00001000) == 0x00001000)) {
+          to_bitField0_ |= 0x00000800;
+        }
+        result.checksum_ = checksum_;
+        if (((from_bitField0_ & 0x00002000) == 0x00002000)) {
+          to_bitField0_ |= 0x00001000;
+        }
+        result.manualSeverity_ = manualSeverity_;
+        if (((from_bitField0_ & 0x00004000) == 0x00004000)) {
+          to_bitField0_ |= 0x00002000;
+        }
+        result.reporter_ = reporter_;
+        if (((from_bitField0_ & 0x00008000) == 0x00008000)) {
+          to_bitField0_ |= 0x00004000;
+        }
+        result.assignee_ = assignee_;
+        if (((from_bitField0_ & 0x00010000) == 0x00010000)) {
+          to_bitField0_ |= 0x00008000;
+        }
+        result.actionPlanKey_ = actionPlanKey_;
+        if (((from_bitField0_ & 0x00020000) == 0x00020000)) {
+          to_bitField0_ |= 0x00010000;
+        }
+        result.attributes_ = attributes_;
+        if (((from_bitField0_ & 0x00040000) == 0x00040000)) {
+          to_bitField0_ |= 0x00020000;
+        }
+        result.authorLogin_ = authorLogin_;
+        if (((from_bitField0_ & 0x00080000) == 0x00080000)) {
+          to_bitField0_ |= 0x00040000;
+        }
+        result.creationDate_ = creationDate_;
+        if (((from_bitField0_ & 0x00100000) == 0x00100000)) {
+          to_bitField0_ |= 0x00080000;
+        }
+        result.closeDate_ = closeDate_;
+        if (((from_bitField0_ & 0x00200000) == 0x00200000)) {
+          to_bitField0_ |= 0x00100000;
+        }
+        result.updateDate_ = updateDate_;
+        if (((from_bitField0_ & 0x00400000) == 0x00400000)) {
+          to_bitField0_ |= 0x00200000;
+        }
+        result.selectedAt_ = selectedAt_;
+        if (((from_bitField0_ & 0x00800000) == 0x00800000)) {
+          to_bitField0_ |= 0x00400000;
+        }
+        result.diffFields_ = diffFields_;
+        if (((from_bitField0_ & 0x01000000) == 0x01000000)) {
+          to_bitField0_ |= 0x00800000;
+        }
+        result.isChanged_ = isChanged_;
+        if (((from_bitField0_ & 0x02000000) == 0x02000000)) {
+          to_bitField0_ |= 0x01000000;
+        }
+        result.mustSendNotification_ = mustSendNotification_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.sonar.batch.protocol.output.BatchOutput.ReportIssue) {
+          return mergeFrom((org.sonar.batch.protocol.output.BatchOutput.ReportIssue)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.sonar.batch.protocol.output.BatchOutput.ReportIssue other) {
+        if (other == org.sonar.batch.protocol.output.BatchOutput.ReportIssue.getDefaultInstance()) return this;
+        if (other.hasRuleRepository()) {
+          bitField0_ |= 0x00000001;
+          ruleRepository_ = other.ruleRepository_;
+          onChanged();
+        }
+        if (other.hasRuleKey()) {
+          bitField0_ |= 0x00000002;
+          ruleKey_ = other.ruleKey_;
+          onChanged();
+        }
+        if (other.hasLine()) {
+          setLine(other.getLine());
+        }
+        if (other.hasMsg()) {
+          bitField0_ |= 0x00000008;
+          msg_ = other.msg_;
+          onChanged();
+        }
+        if (other.hasSeverity()) {
+          setSeverity(other.getSeverity());
+        }
+        if (!other.tags_.isEmpty()) {
+          if (tags_.isEmpty()) {
+            tags_ = other.tags_;
+            bitField0_ = (bitField0_ & ~0x00000020);
+          } else {
+            ensureTagsIsMutable();
+            tags_.addAll(other.tags_);
+          }
+          onChanged();
+        }
+        if (other.hasEffortToFix()) {
+          setEffortToFix(other.getEffortToFix());
+        }
+        if (other.hasIsNew()) {
+          setIsNew(other.getIsNew());
+        }
+        if (other.hasUuid()) {
+          bitField0_ |= 0x00000100;
+          uuid_ = other.uuid_;
+          onChanged();
+        }
+        if (other.hasDebtInMinutes()) {
+          setDebtInMinutes(other.getDebtInMinutes());
+        }
+        if (other.hasResolution()) {
+          bitField0_ |= 0x00000400;
+          resolution_ = other.resolution_;
+          onChanged();
+        }
+        if (other.hasStatus()) {
+          bitField0_ |= 0x00000800;
+          status_ = other.status_;
+          onChanged();
+        }
+        if (other.hasChecksum()) {
+          bitField0_ |= 0x00001000;
+          checksum_ = other.checksum_;
+          onChanged();
+        }
+        if (other.hasManualSeverity()) {
+          setManualSeverity(other.getManualSeverity());
+        }
+        if (other.hasReporter()) {
+          bitField0_ |= 0x00004000;
+          reporter_ = other.reporter_;
+          onChanged();
+        }
+        if (other.hasAssignee()) {
+          bitField0_ |= 0x00008000;
+          assignee_ = other.assignee_;
+          onChanged();
+        }
+        if (other.hasActionPlanKey()) {
+          bitField0_ |= 0x00010000;
+          actionPlanKey_ = other.actionPlanKey_;
+          onChanged();
+        }
+        if (other.hasAttributes()) {
+          bitField0_ |= 0x00020000;
+          attributes_ = other.attributes_;
+          onChanged();
+        }
+        if (other.hasAuthorLogin()) {
+          bitField0_ |= 0x00040000;
+          authorLogin_ = other.authorLogin_;
+          onChanged();
+        }
+        if (other.hasCreationDate()) {
+          setCreationDate(other.getCreationDate());
+        }
+        if (other.hasCloseDate()) {
+          setCloseDate(other.getCloseDate());
+        }
+        if (other.hasUpdateDate()) {
+          setUpdateDate(other.getUpdateDate());
+        }
+        if (other.hasSelectedAt()) {
+          setSelectedAt(other.getSelectedAt());
+        }
+        if (other.hasDiffFields()) {
+          bitField0_ |= 0x00800000;
+          diffFields_ = other.diffFields_;
+          onChanged();
+        }
+        if (other.hasIsChanged()) {
+          setIsChanged(other.getIsChanged());
+        }
+        if (other.hasMustSendNotification()) {
+          setMustSendNotification(other.getMustSendNotification());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.sonar.batch.protocol.output.BatchOutput.ReportIssue parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.sonar.batch.protocol.output.BatchOutput.ReportIssue) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      private java.lang.Object ruleRepository_ = "";
+      /**
+       * <code>optional string rule_repository = 1;</code>
+       */
+      public boolean hasRuleRepository() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>optional string rule_repository = 1;</code>
+       */
+      public java.lang.String getRuleRepository() {
+        java.lang.Object ref = ruleRepository_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            ruleRepository_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string rule_repository = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getRuleRepositoryBytes() {
+        java.lang.Object ref = ruleRepository_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          ruleRepository_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string rule_repository = 1;</code>
+       */
+      public Builder setRuleRepository(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        ruleRepository_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string rule_repository = 1;</code>
+       */
+      public Builder clearRuleRepository() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        ruleRepository_ = getDefaultInstance().getRuleRepository();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string rule_repository = 1;</code>
+       */
+      public Builder setRuleRepositoryBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+        ruleRepository_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object ruleKey_ = "";
+      /**
+       * <code>optional string rule_key = 2;</code>
+       */
+      public boolean hasRuleKey() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>optional string rule_key = 2;</code>
+       */
+      public java.lang.String getRuleKey() {
+        java.lang.Object ref = ruleKey_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            ruleKey_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string rule_key = 2;</code>
+       */
+      public com.google.protobuf.ByteString
+          getRuleKeyBytes() {
+        java.lang.Object ref = ruleKey_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          ruleKey_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string rule_key = 2;</code>
+       */
+      public Builder setRuleKey(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        ruleKey_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string rule_key = 2;</code>
+       */
+      public Builder clearRuleKey() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        ruleKey_ = getDefaultInstance().getRuleKey();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string rule_key = 2;</code>
+       */
+      public Builder setRuleKeyBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        ruleKey_ = value;
+        onChanged();
+        return this;
+      }
+
+      private int line_ ;
+      /**
+       * <code>optional int32 line = 3;</code>
+       */
+      public boolean hasLine() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>optional int32 line = 3;</code>
+       */
+      public int getLine() {
+        return line_;
+      }
+      /**
+       * <code>optional int32 line = 3;</code>
+       */
+      public Builder setLine(int value) {
+        bitField0_ |= 0x00000004;
+        line_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 line = 3;</code>
+       */
+      public Builder clearLine() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        line_ = 0;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object msg_ = "";
+      /**
+       * <code>optional string msg = 4;</code>
+       */
+      public boolean hasMsg() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>optional string msg = 4;</code>
+       */
+      public java.lang.String getMsg() {
+        java.lang.Object ref = msg_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            msg_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string msg = 4;</code>
+       */
+      public com.google.protobuf.ByteString
+          getMsgBytes() {
+        java.lang.Object ref = msg_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          msg_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string msg = 4;</code>
+       */
+      public Builder setMsg(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000008;
+        msg_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string msg = 4;</code>
+       */
+      public Builder clearMsg() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        msg_ = getDefaultInstance().getMsg();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string msg = 4;</code>
+       */
+      public Builder setMsgBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000008;
+        msg_ = value;
+        onChanged();
+        return this;
+      }
+
+      private org.sonar.batch.protocol.Constants.Severity severity_ = org.sonar.batch.protocol.Constants.Severity.INFO;
+      /**
+       * <code>optional .Severity severity = 5;</code>
+       */
+      public boolean hasSeverity() {
+        return ((bitField0_ & 0x00000010) == 0x00000010);
+      }
+      /**
+       * <code>optional .Severity severity = 5;</code>
+       */
+      public org.sonar.batch.protocol.Constants.Severity getSeverity() {
+        return severity_;
+      }
+      /**
+       * <code>optional .Severity severity = 5;</code>
+       */
+      public Builder setSeverity(org.sonar.batch.protocol.Constants.Severity value) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        bitField0_ |= 0x00000010;
+        severity_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional .Severity severity = 5;</code>
+       */
+      public Builder clearSeverity() {
+        bitField0_ = (bitField0_ & ~0x00000010);
+        severity_ = org.sonar.batch.protocol.Constants.Severity.INFO;
+        onChanged();
+        return this;
+      }
+
+      private com.google.protobuf.LazyStringList tags_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+      private void ensureTagsIsMutable() {
+        if (!((bitField0_ & 0x00000020) == 0x00000020)) {
+          tags_ = new com.google.protobuf.LazyStringArrayList(tags_);
+          bitField0_ |= 0x00000020;
+         }
+      }
+      /**
+       * <code>repeated string tags = 6;</code>
+       */
+      public com.google.protobuf.ProtocolStringList
+          getTagsList() {
+        return tags_.getUnmodifiableView();
+      }
+      /**
+       * <code>repeated string tags = 6;</code>
+       */
+      public int getTagsCount() {
+        return tags_.size();
+      }
+      /**
+       * <code>repeated string tags = 6;</code>
+       */
+      public java.lang.String getTags(int index) {
+        return tags_.get(index);
+      }
+      /**
+       * <code>repeated string tags = 6;</code>
+       */
+      public com.google.protobuf.ByteString
+          getTagsBytes(int index) {
+        return tags_.getByteString(index);
+      }
+      /**
+       * <code>repeated string tags = 6;</code>
+       */
+      public Builder setTags(
+          int index, java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  ensureTagsIsMutable();
+        tags_.set(index, value);
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>repeated string tags = 6;</code>
+       */
+      public Builder addTags(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  ensureTagsIsMutable();
+        tags_.add(value);
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>repeated string tags = 6;</code>
+       */
+      public Builder addAllTags(
+          java.lang.Iterable<java.lang.String> values) {
+        ensureTagsIsMutable();
+        com.google.protobuf.AbstractMessageLite.Builder.addAll(
+            values, tags_);
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>repeated string tags = 6;</code>
+       */
+      public Builder clearTags() {
+        tags_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+        bitField0_ = (bitField0_ & ~0x00000020);
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>repeated string tags = 6;</code>
+       */
+      public Builder addTagsBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  ensureTagsIsMutable();
+        tags_.add(value);
+        onChanged();
+        return this;
+      }
+
+      private double effortToFix_ ;
+      /**
+       * <code>optional double effort_to_fix = 7;</code>
+       *
+       * <pre>
+       * temporary fields during development of computation stack
+       * </pre>
+       */
+      public boolean hasEffortToFix() {
+        return ((bitField0_ & 0x00000040) == 0x00000040);
+      }
+      /**
+       * <code>optional double effort_to_fix = 7;</code>
+       *
+       * <pre>
+       * temporary fields during development of computation stack
+       * </pre>
+       */
+      public double getEffortToFix() {
+        return effortToFix_;
+      }
+      /**
+       * <code>optional double effort_to_fix = 7;</code>
+       *
+       * <pre>
+       * temporary fields during development of computation stack
+       * </pre>
+       */
+      public Builder setEffortToFix(double value) {
+        bitField0_ |= 0x00000040;
+        effortToFix_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional double effort_to_fix = 7;</code>
+       *
+       * <pre>
+       * temporary fields during development of computation stack
+       * </pre>
+       */
+      public Builder clearEffortToFix() {
+        bitField0_ = (bitField0_ & ~0x00000040);
+        effortToFix_ = 0D;
+        onChanged();
+        return this;
+      }
+
+      private boolean isNew_ ;
+      /**
+       * <code>optional bool is_new = 8;</code>
+       */
+      public boolean hasIsNew() {
+        return ((bitField0_ & 0x00000080) == 0x00000080);
+      }
+      /**
+       * <code>optional bool is_new = 8;</code>
+       */
+      public boolean getIsNew() {
+        return isNew_;
+      }
+      /**
+       * <code>optional bool is_new = 8;</code>
+       */
+      public Builder setIsNew(boolean value) {
+        bitField0_ |= 0x00000080;
+        isNew_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bool is_new = 8;</code>
+       */
+      public Builder clearIsNew() {
+        bitField0_ = (bitField0_ & ~0x00000080);
+        isNew_ = false;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object uuid_ = "";
+      /**
+       * <code>optional string uuid = 9;</code>
+       */
+      public boolean hasUuid() {
+        return ((bitField0_ & 0x00000100) == 0x00000100);
+      }
+      /**
+       * <code>optional string uuid = 9;</code>
+       */
+      public java.lang.String getUuid() {
+        java.lang.Object ref = uuid_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            uuid_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string uuid = 9;</code>
+       */
+      public com.google.protobuf.ByteString
+          getUuidBytes() {
+        java.lang.Object ref = uuid_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          uuid_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string uuid = 9;</code>
+       */
+      public Builder setUuid(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000100;
+        uuid_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string uuid = 9;</code>
+       */
+      public Builder clearUuid() {
+        bitField0_ = (bitField0_ & ~0x00000100);
+        uuid_ = getDefaultInstance().getUuid();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string uuid = 9;</code>
+       */
+      public Builder setUuidBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000100;
+        uuid_ = value;
+        onChanged();
+        return this;
+      }
+
+      private long debtInMinutes_ ;
+      /**
+       * <code>optional int64 debt_in_minutes = 10;</code>
+       */
+      public boolean hasDebtInMinutes() {
+        return ((bitField0_ & 0x00000200) == 0x00000200);
+      }
+      /**
+       * <code>optional int64 debt_in_minutes = 10;</code>
+       */
+      public long getDebtInMinutes() {
+        return debtInMinutes_;
+      }
+      /**
+       * <code>optional int64 debt_in_minutes = 10;</code>
+       */
+      public Builder setDebtInMinutes(long value) {
+        bitField0_ |= 0x00000200;
+        debtInMinutes_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int64 debt_in_minutes = 10;</code>
+       */
+      public Builder clearDebtInMinutes() {
+        bitField0_ = (bitField0_ & ~0x00000200);
+        debtInMinutes_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object resolution_ = "";
+      /**
+       * <code>optional string resolution = 11;</code>
+       */
+      public boolean hasResolution() {
+        return ((bitField0_ & 0x00000400) == 0x00000400);
+      }
+      /**
+       * <code>optional string resolution = 11;</code>
+       */
+      public java.lang.String getResolution() {
+        java.lang.Object ref = resolution_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            resolution_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string resolution = 11;</code>
+       */
+      public com.google.protobuf.ByteString
+          getResolutionBytes() {
+        java.lang.Object ref = resolution_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          resolution_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string resolution = 11;</code>
+       */
+      public Builder setResolution(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000400;
+        resolution_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string resolution = 11;</code>
+       */
+      public Builder clearResolution() {
+        bitField0_ = (bitField0_ & ~0x00000400);
+        resolution_ = getDefaultInstance().getResolution();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string resolution = 11;</code>
+       */
+      public Builder setResolutionBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000400;
+        resolution_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object status_ = "";
+      /**
+       * <code>optional string status = 12;</code>
+       */
+      public boolean hasStatus() {
+        return ((bitField0_ & 0x00000800) == 0x00000800);
+      }
+      /**
+       * <code>optional string status = 12;</code>
+       */
+      public java.lang.String getStatus() {
+        java.lang.Object ref = status_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            status_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string status = 12;</code>
+       */
+      public com.google.protobuf.ByteString
+          getStatusBytes() {
+        java.lang.Object ref = status_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          status_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string status = 12;</code>
+       */
+      public Builder setStatus(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000800;
+        status_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string status = 12;</code>
+       */
+      public Builder clearStatus() {
+        bitField0_ = (bitField0_ & ~0x00000800);
+        status_ = getDefaultInstance().getStatus();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string status = 12;</code>
+       */
+      public Builder setStatusBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000800;
+        status_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object checksum_ = "";
+      /**
+       * <code>optional string checksum = 13;</code>
+       */
+      public boolean hasChecksum() {
+        return ((bitField0_ & 0x00001000) == 0x00001000);
+      }
+      /**
+       * <code>optional string checksum = 13;</code>
+       */
+      public java.lang.String getChecksum() {
+        java.lang.Object ref = checksum_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            checksum_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string checksum = 13;</code>
+       */
+      public com.google.protobuf.ByteString
+          getChecksumBytes() {
+        java.lang.Object ref = checksum_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          checksum_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string checksum = 13;</code>
+       */
+      public Builder setChecksum(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00001000;
+        checksum_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string checksum = 13;</code>
+       */
+      public Builder clearChecksum() {
+        bitField0_ = (bitField0_ & ~0x00001000);
+        checksum_ = getDefaultInstance().getChecksum();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string checksum = 13;</code>
+       */
+      public Builder setChecksumBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00001000;
+        checksum_ = value;
+        onChanged();
+        return this;
+      }
+
+      private boolean manualSeverity_ ;
+      /**
+       * <code>optional bool manual_severity = 14;</code>
+       */
+      public boolean hasManualSeverity() {
+        return ((bitField0_ & 0x00002000) == 0x00002000);
+      }
+      /**
+       * <code>optional bool manual_severity = 14;</code>
+       */
+      public boolean getManualSeverity() {
+        return manualSeverity_;
+      }
+      /**
+       * <code>optional bool manual_severity = 14;</code>
+       */
+      public Builder setManualSeverity(boolean value) {
+        bitField0_ |= 0x00002000;
+        manualSeverity_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bool manual_severity = 14;</code>
+       */
+      public Builder clearManualSeverity() {
+        bitField0_ = (bitField0_ & ~0x00002000);
+        manualSeverity_ = false;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object reporter_ = "";
+      /**
+       * <code>optional string reporter = 15;</code>
+       */
+      public boolean hasReporter() {
+        return ((bitField0_ & 0x00004000) == 0x00004000);
+      }
+      /**
+       * <code>optional string reporter = 15;</code>
+       */
+      public java.lang.String getReporter() {
+        java.lang.Object ref = reporter_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            reporter_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string reporter = 15;</code>
+       */
+      public com.google.protobuf.ByteString
+          getReporterBytes() {
+        java.lang.Object ref = reporter_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          reporter_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string reporter = 15;</code>
+       */
+      public Builder setReporter(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00004000;
+        reporter_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string reporter = 15;</code>
+       */
+      public Builder clearReporter() {
+        bitField0_ = (bitField0_ & ~0x00004000);
+        reporter_ = getDefaultInstance().getReporter();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string reporter = 15;</code>
+       */
+      public Builder setReporterBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00004000;
+        reporter_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object assignee_ = "";
+      /**
+       * <code>optional string assignee = 16;</code>
+       */
+      public boolean hasAssignee() {
+        return ((bitField0_ & 0x00008000) == 0x00008000);
+      }
+      /**
+       * <code>optional string assignee = 16;</code>
+       */
+      public java.lang.String getAssignee() {
+        java.lang.Object ref = assignee_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            assignee_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string assignee = 16;</code>
+       */
+      public com.google.protobuf.ByteString
+          getAssigneeBytes() {
+        java.lang.Object ref = assignee_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          assignee_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string assignee = 16;</code>
+       */
+      public Builder setAssignee(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00008000;
+        assignee_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string assignee = 16;</code>
+       */
+      public Builder clearAssignee() {
+        bitField0_ = (bitField0_ & ~0x00008000);
+        assignee_ = getDefaultInstance().getAssignee();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string assignee = 16;</code>
+       */
+      public Builder setAssigneeBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00008000;
+        assignee_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object actionPlanKey_ = "";
+      /**
+       * <code>optional string action_plan_key = 17;</code>
+       */
+      public boolean hasActionPlanKey() {
+        return ((bitField0_ & 0x00010000) == 0x00010000);
+      }
+      /**
+       * <code>optional string action_plan_key = 17;</code>
+       */
+      public java.lang.String getActionPlanKey() {
+        java.lang.Object ref = actionPlanKey_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            actionPlanKey_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string action_plan_key = 17;</code>
+       */
+      public com.google.protobuf.ByteString
+          getActionPlanKeyBytes() {
+        java.lang.Object ref = actionPlanKey_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          actionPlanKey_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string action_plan_key = 17;</code>
+       */
+      public Builder setActionPlanKey(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00010000;
+        actionPlanKey_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string action_plan_key = 17;</code>
+       */
+      public Builder clearActionPlanKey() {
+        bitField0_ = (bitField0_ & ~0x00010000);
+        actionPlanKey_ = getDefaultInstance().getActionPlanKey();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string action_plan_key = 17;</code>
+       */
+      public Builder setActionPlanKeyBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00010000;
+        actionPlanKey_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object attributes_ = "";
+      /**
+       * <code>optional string attributes = 18;</code>
+       */
+      public boolean hasAttributes() {
+        return ((bitField0_ & 0x00020000) == 0x00020000);
+      }
+      /**
+       * <code>optional string attributes = 18;</code>
+       */
+      public java.lang.String getAttributes() {
+        java.lang.Object ref = attributes_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            attributes_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string attributes = 18;</code>
+       */
+      public com.google.protobuf.ByteString
+          getAttributesBytes() {
+        java.lang.Object ref = attributes_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          attributes_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string attributes = 18;</code>
+       */
+      public Builder setAttributes(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00020000;
+        attributes_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string attributes = 18;</code>
+       */
+      public Builder clearAttributes() {
+        bitField0_ = (bitField0_ & ~0x00020000);
+        attributes_ = getDefaultInstance().getAttributes();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string attributes = 18;</code>
+       */
+      public Builder setAttributesBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00020000;
+        attributes_ = value;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object authorLogin_ = "";
+      /**
+       * <code>optional string author_login = 19;</code>
+       */
+      public boolean hasAuthorLogin() {
+        return ((bitField0_ & 0x00040000) == 0x00040000);
+      }
+      /**
+       * <code>optional string author_login = 19;</code>
+       */
+      public java.lang.String getAuthorLogin() {
+        java.lang.Object ref = authorLogin_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            authorLogin_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string author_login = 19;</code>
+       */
+      public com.google.protobuf.ByteString
+          getAuthorLoginBytes() {
+        java.lang.Object ref = authorLogin_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          authorLogin_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string author_login = 19;</code>
+       */
+      public Builder setAuthorLogin(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00040000;
+        authorLogin_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string author_login = 19;</code>
+       */
+      public Builder clearAuthorLogin() {
+        bitField0_ = (bitField0_ & ~0x00040000);
+        authorLogin_ = getDefaultInstance().getAuthorLogin();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string author_login = 19;</code>
+       */
+      public Builder setAuthorLoginBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00040000;
+        authorLogin_ = value;
+        onChanged();
+        return this;
+      }
+
+      private long creationDate_ ;
+      /**
+       * <code>optional int64 creation_date = 20;</code>
+       */
+      public boolean hasCreationDate() {
+        return ((bitField0_ & 0x00080000) == 0x00080000);
+      }
+      /**
+       * <code>optional int64 creation_date = 20;</code>
+       */
+      public long getCreationDate() {
+        return creationDate_;
+      }
+      /**
+       * <code>optional int64 creation_date = 20;</code>
+       */
+      public Builder setCreationDate(long value) {
+        bitField0_ |= 0x00080000;
+        creationDate_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int64 creation_date = 20;</code>
+       */
+      public Builder clearCreationDate() {
+        bitField0_ = (bitField0_ & ~0x00080000);
+        creationDate_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      private long closeDate_ ;
+      /**
+       * <code>optional int64 close_date = 21;</code>
+       */
+      public boolean hasCloseDate() {
+        return ((bitField0_ & 0x00100000) == 0x00100000);
+      }
+      /**
+       * <code>optional int64 close_date = 21;</code>
+       */
+      public long getCloseDate() {
+        return closeDate_;
+      }
+      /**
+       * <code>optional int64 close_date = 21;</code>
+       */
+      public Builder setCloseDate(long value) {
+        bitField0_ |= 0x00100000;
+        closeDate_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int64 close_date = 21;</code>
+       */
+      public Builder clearCloseDate() {
+        bitField0_ = (bitField0_ & ~0x00100000);
+        closeDate_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      private long updateDate_ ;
+      /**
+       * <code>optional int64 update_date = 22;</code>
+       */
+      public boolean hasUpdateDate() {
+        return ((bitField0_ & 0x00200000) == 0x00200000);
+      }
+      /**
+       * <code>optional int64 update_date = 22;</code>
+       */
+      public long getUpdateDate() {
+        return updateDate_;
+      }
+      /**
+       * <code>optional int64 update_date = 22;</code>
+       */
+      public Builder setUpdateDate(long value) {
+        bitField0_ |= 0x00200000;
+        updateDate_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int64 update_date = 22;</code>
+       */
+      public Builder clearUpdateDate() {
+        bitField0_ = (bitField0_ & ~0x00200000);
+        updateDate_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      private long selectedAt_ ;
+      /**
+       * <code>optional int64 selected_at = 23;</code>
+       */
+      public boolean hasSelectedAt() {
+        return ((bitField0_ & 0x00400000) == 0x00400000);
+      }
+      /**
+       * <code>optional int64 selected_at = 23;</code>
+       */
+      public long getSelectedAt() {
+        return selectedAt_;
+      }
+      /**
+       * <code>optional int64 selected_at = 23;</code>
+       */
+      public Builder setSelectedAt(long value) {
+        bitField0_ |= 0x00400000;
+        selectedAt_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int64 selected_at = 23;</code>
+       */
+      public Builder clearSelectedAt() {
+        bitField0_ = (bitField0_ & ~0x00400000);
+        selectedAt_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      private java.lang.Object diffFields_ = "";
+      /**
+       * <code>optional string diff_fields = 24;</code>
+       */
+      public boolean hasDiffFields() {
+        return ((bitField0_ & 0x00800000) == 0x00800000);
+      }
+      /**
+       * <code>optional string diff_fields = 24;</code>
+       */
+      public java.lang.String getDiffFields() {
+        java.lang.Object ref = diffFields_;
+        if (!(ref instanceof java.lang.String)) {
+          com.google.protobuf.ByteString bs =
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            diffFields_ = s;
+          }
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string diff_fields = 24;</code>
+       */
+      public com.google.protobuf.ByteString
+          getDiffFieldsBytes() {
+        java.lang.Object ref = diffFields_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          diffFields_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string diff_fields = 24;</code>
+       */
+      public Builder setDiffFields(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00800000;
+        diffFields_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string diff_fields = 24;</code>
+       */
+      public Builder clearDiffFields() {
+        bitField0_ = (bitField0_ & ~0x00800000);
+        diffFields_ = getDefaultInstance().getDiffFields();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string diff_fields = 24;</code>
+       */
+      public Builder setDiffFieldsBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00800000;
+        diffFields_ = value;
+        onChanged();
+        return this;
+      }
+
+      private boolean isChanged_ ;
+      /**
+       * <code>optional bool is_changed = 25;</code>
+       */
+      public boolean hasIsChanged() {
+        return ((bitField0_ & 0x01000000) == 0x01000000);
+      }
+      /**
+       * <code>optional bool is_changed = 25;</code>
+       */
+      public boolean getIsChanged() {
+        return isChanged_;
+      }
+      /**
+       * <code>optional bool is_changed = 25;</code>
+       */
+      public Builder setIsChanged(boolean value) {
+        bitField0_ |= 0x01000000;
+        isChanged_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bool is_changed = 25;</code>
+       */
+      public Builder clearIsChanged() {
+        bitField0_ = (bitField0_ & ~0x01000000);
+        isChanged_ = false;
+        onChanged();
+        return this;
+      }
+
+      private boolean mustSendNotification_ ;
+      /**
+       * <code>optional bool must_send_notification = 26;</code>
+       */
+      public boolean hasMustSendNotification() {
+        return ((bitField0_ & 0x02000000) == 0x02000000);
+      }
+      /**
+       * <code>optional bool must_send_notification = 26;</code>
+       */
+      public boolean getMustSendNotification() {
+        return mustSendNotification_;
+      }
+      /**
+       * <code>optional bool must_send_notification = 26;</code>
+       */
+      public Builder setMustSendNotification(boolean value) {
+        bitField0_ |= 0x02000000;
+        mustSendNotification_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional bool must_send_notification = 26;</code>
+       */
+      public Builder clearMustSendNotification() {
+        bitField0_ = (bitField0_ & ~0x02000000);
+        mustSendNotification_ = false;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:ReportIssue)
+    }
+
+    static {
+      defaultInstance = new ReportIssue(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:ReportIssue)
+  }
+
+  public interface ReportIssuesOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:ReportIssues)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>optional int32 component_ref = 1;</code>
+     */
+    boolean hasComponentRef();
+    /**
+     * <code>optional int32 component_ref = 1;</code>
+     */
+    int getComponentRef();
+
+    /**
+     * <code>repeated .ReportIssue list = 2;</code>
+     */
+    java.util.List<org.sonar.batch.protocol.output.BatchOutput.ReportIssue> 
+        getListList();
+    /**
+     * <code>repeated .ReportIssue list = 2;</code>
+     */
+    org.sonar.batch.protocol.output.BatchOutput.ReportIssue getList(int index);
+    /**
+     * <code>repeated .ReportIssue list = 2;</code>
+     */
+    int getListCount();
+    /**
+     * <code>repeated .ReportIssue list = 2;</code>
+     */
+    java.util.List<? extends org.sonar.batch.protocol.output.BatchOutput.ReportIssueOrBuilder> 
+        getListOrBuilderList();
+    /**
+     * <code>repeated .ReportIssue list = 2;</code>
+     */
+    org.sonar.batch.protocol.output.BatchOutput.ReportIssueOrBuilder getListOrBuilder(
+        int index);
+  }
+  /**
+   * Protobuf type {@code ReportIssues}
+   */
+  public static final class ReportIssues extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:ReportIssues)
+      ReportIssuesOrBuilder {
+    // Use ReportIssues.newBuilder() to construct.
+    private ReportIssues(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private ReportIssues(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final ReportIssues defaultInstance;
+    public static ReportIssues getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public ReportIssues getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private ReportIssues(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              bitField0_ |= 0x00000001;
+              componentRef_ = input.readInt32();
+              break;
+            }
+            case 18: {
+              if (!((mutable_bitField0_ & 0x00000002) == 0x00000002)) {
+                list_ = new java.util.ArrayList<org.sonar.batch.protocol.output.BatchOutput.ReportIssue>();
+                mutable_bitField0_ |= 0x00000002;
+              }
+              list_.add(input.readMessage(org.sonar.batch.protocol.output.BatchOutput.ReportIssue.PARSER, extensionRegistry));
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        if (((mutable_bitField0_ & 0x00000002) == 0x00000002)) {
+          list_ = java.util.Collections.unmodifiableList(list_);
+        }
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportIssues_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportIssues_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.sonar.batch.protocol.output.BatchOutput.ReportIssues.class, org.sonar.batch.protocol.output.BatchOutput.ReportIssues.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<ReportIssues> PARSER =
+        new com.google.protobuf.AbstractParser<ReportIssues>() {
+      public ReportIssues parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new ReportIssues(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<ReportIssues> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    public static final int COMPONENT_REF_FIELD_NUMBER = 1;
+    private int componentRef_;
+    /**
+     * <code>optional int32 component_ref = 1;</code>
+     */
+    public boolean hasComponentRef() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>optional int32 component_ref = 1;</code>
+     */
+    public int getComponentRef() {
+      return componentRef_;
+    }
+
+    public static final int LIST_FIELD_NUMBER = 2;
+    private java.util.List<org.sonar.batch.protocol.output.BatchOutput.ReportIssue> list_;
+    /**
+     * <code>repeated .ReportIssue list = 2;</code>
+     */
+    public java.util.List<org.sonar.batch.protocol.output.BatchOutput.ReportIssue> getListList() {
+      return list_;
+    }
+    /**
+     * <code>repeated .ReportIssue list = 2;</code>
+     */
+    public java.util.List<? extends org.sonar.batch.protocol.output.BatchOutput.ReportIssueOrBuilder> 
+        getListOrBuilderList() {
+      return list_;
+    }
+    /**
+     * <code>repeated .ReportIssue list = 2;</code>
+     */
+    public int getListCount() {
+      return list_.size();
+    }
+    /**
+     * <code>repeated .ReportIssue list = 2;</code>
+     */
+    public org.sonar.batch.protocol.output.BatchOutput.ReportIssue getList(int index) {
+      return list_.get(index);
+    }
+    /**
+     * <code>repeated .ReportIssue list = 2;</code>
+     */
+    public org.sonar.batch.protocol.output.BatchOutput.ReportIssueOrBuilder getListOrBuilder(
+        int index) {
+      return list_.get(index);
+    }
+
+    private void initFields() {
+      componentRef_ = 0;
+      list_ = java.util.Collections.emptyList();
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeInt32(1, componentRef_);
+      }
+      for (int i = 0; i < list_.size(); i++) {
+        output.writeMessage(2, list_.get(i));
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt32Size(1, componentRef_);
+      }
+      for (int i = 0; i < list_.size(); i++) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(2, list_.get(i));
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssues parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssues parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssues parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssues parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssues parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssues parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssues parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssues parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssues parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonar.batch.protocol.output.BatchOutput.ReportIssues parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.sonar.batch.protocol.output.BatchOutput.ReportIssues prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code ReportIssues}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:ReportIssues)
+        org.sonar.batch.protocol.output.BatchOutput.ReportIssuesOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportIssues_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportIssues_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.sonar.batch.protocol.output.BatchOutput.ReportIssues.class, org.sonar.batch.protocol.output.BatchOutput.ReportIssues.Builder.class);
+      }
+
+      // Construct using org.sonar.batch.protocol.output.BatchOutput.ReportIssues.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          getListFieldBuilder();
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        componentRef_ = 0;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        if (listBuilder_ == null) {
+          list_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000002);
+        } else {
+          listBuilder_.clear();
+        }
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.sonar.batch.protocol.output.BatchOutput.internal_static_ReportIssues_descriptor;
+      }
+
+      public org.sonar.batch.protocol.output.BatchOutput.ReportIssues getDefaultInstanceForType() {
+        return org.sonar.batch.protocol.output.BatchOutput.ReportIssues.getDefaultInstance();
+      }
+
+      public org.sonar.batch.protocol.output.BatchOutput.ReportIssues build() {
+        org.sonar.batch.protocol.output.BatchOutput.ReportIssues result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.sonar.batch.protocol.output.BatchOutput.ReportIssues buildPartial() {
+        org.sonar.batch.protocol.output.BatchOutput.ReportIssues result = new org.sonar.batch.protocol.output.BatchOutput.ReportIssues(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.componentRef_ = componentRef_;
+        if (listBuilder_ == null) {
+          if (((bitField0_ & 0x00000002) == 0x00000002)) {
+            list_ = java.util.Collections.unmodifiableList(list_);
+            bitField0_ = (bitField0_ & ~0x00000002);
+          }
+          result.list_ = list_;
+        } else {
+          result.list_ = listBuilder_.build();
+        }
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.sonar.batch.protocol.output.BatchOutput.ReportIssues) {
+          return mergeFrom((org.sonar.batch.protocol.output.BatchOutput.ReportIssues)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.sonar.batch.protocol.output.BatchOutput.ReportIssues other) {
+        if (other == org.sonar.batch.protocol.output.BatchOutput.ReportIssues.getDefaultInstance()) return this;
+        if (other.hasComponentRef()) {
+          setComponentRef(other.getComponentRef());
+        }
+        if (listBuilder_ == null) {
+          if (!other.list_.isEmpty()) {
+            if (list_.isEmpty()) {
+              list_ = other.list_;
+              bitField0_ = (bitField0_ & ~0x00000002);
+            } else {
+              ensureListIsMutable();
+              list_.addAll(other.list_);
+            }
+            onChanged();
+          }
+        } else {
+          if (!other.list_.isEmpty()) {
+            if (listBuilder_.isEmpty()) {
+              listBuilder_.dispose();
+              listBuilder_ = null;
+              list_ = other.list_;
+              bitField0_ = (bitField0_ & ~0x00000002);
+              listBuilder_ = 
+                com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
+                   getListFieldBuilder() : null;
+            } else {
+              listBuilder_.addAllMessages(other.list_);
+            }
+          }
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.sonar.batch.protocol.output.BatchOutput.ReportIssues parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.sonar.batch.protocol.output.BatchOutput.ReportIssues) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      private int componentRef_ ;
+      /**
+       * <code>optional int32 component_ref = 1;</code>
+       */
+      public boolean hasComponentRef() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>optional int32 component_ref = 1;</code>
+       */
+      public int getComponentRef() {
+        return componentRef_;
+      }
+      /**
+       * <code>optional int32 component_ref = 1;</code>
+       */
+      public Builder setComponentRef(int value) {
+        bitField0_ |= 0x00000001;
+        componentRef_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int32 component_ref = 1;</code>
+       */
+      public Builder clearComponentRef() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        componentRef_ = 0;
+        onChanged();
+        return this;
+      }
+
+      private java.util.List<org.sonar.batch.protocol.output.BatchOutput.ReportIssue> list_ =
+        java.util.Collections.emptyList();
+      private void ensureListIsMutable() {
+        if (!((bitField0_ & 0x00000002) == 0x00000002)) {
+          list_ = new java.util.ArrayList<org.sonar.batch.protocol.output.BatchOutput.ReportIssue>(list_);
+          bitField0_ |= 0x00000002;
+         }
+      }
+
+      private com.google.protobuf.RepeatedFieldBuilder<
+          org.sonar.batch.protocol.output.BatchOutput.ReportIssue, org.sonar.batch.protocol.output.BatchOutput.ReportIssue.Builder, org.sonar.batch.protocol.output.BatchOutput.ReportIssueOrBuilder> listBuilder_;
+
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public java.util.List<org.sonar.batch.protocol.output.BatchOutput.ReportIssue> getListList() {
+        if (listBuilder_ == null) {
+          return java.util.Collections.unmodifiableList(list_);
+        } else {
+          return listBuilder_.getMessageList();
+        }
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public int getListCount() {
+        if (listBuilder_ == null) {
+          return list_.size();
+        } else {
+          return listBuilder_.getCount();
+        }
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public org.sonar.batch.protocol.output.BatchOutput.ReportIssue getList(int index) {
+        if (listBuilder_ == null) {
+          return list_.get(index);
+        } else {
+          return listBuilder_.getMessage(index);
+        }
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public Builder setList(
+          int index, org.sonar.batch.protocol.output.BatchOutput.ReportIssue value) {
+        if (listBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureListIsMutable();
+          list_.set(index, value);
+          onChanged();
+        } else {
+          listBuilder_.setMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public Builder setList(
+          int index, org.sonar.batch.protocol.output.BatchOutput.ReportIssue.Builder builderForValue) {
+        if (listBuilder_ == null) {
+          ensureListIsMutable();
+          list_.set(index, builderForValue.build());
+          onChanged();
+        } else {
+          listBuilder_.setMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public Builder addList(org.sonar.batch.protocol.output.BatchOutput.ReportIssue value) {
+        if (listBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureListIsMutable();
+          list_.add(value);
+          onChanged();
+        } else {
+          listBuilder_.addMessage(value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public Builder addList(
+          int index, org.sonar.batch.protocol.output.BatchOutput.ReportIssue value) {
+        if (listBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureListIsMutable();
+          list_.add(index, value);
+          onChanged();
+        } else {
+          listBuilder_.addMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public Builder addList(
+          org.sonar.batch.protocol.output.BatchOutput.ReportIssue.Builder builderForValue) {
+        if (listBuilder_ == null) {
+          ensureListIsMutable();
+          list_.add(builderForValue.build());
+          onChanged();
+        } else {
+          listBuilder_.addMessage(builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public Builder addList(
+          int index, org.sonar.batch.protocol.output.BatchOutput.ReportIssue.Builder builderForValue) {
+        if (listBuilder_ == null) {
+          ensureListIsMutable();
+          list_.add(index, builderForValue.build());
+          onChanged();
+        } else {
+          listBuilder_.addMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public Builder addAllList(
+          java.lang.Iterable<? extends org.sonar.batch.protocol.output.BatchOutput.ReportIssue> values) {
+        if (listBuilder_ == null) {
+          ensureListIsMutable();
+          com.google.protobuf.AbstractMessageLite.Builder.addAll(
+              values, list_);
+          onChanged();
+        } else {
+          listBuilder_.addAllMessages(values);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public Builder clearList() {
+        if (listBuilder_ == null) {
+          list_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000002);
+          onChanged();
+        } else {
+          listBuilder_.clear();
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public Builder removeList(int index) {
+        if (listBuilder_ == null) {
+          ensureListIsMutable();
+          list_.remove(index);
+          onChanged();
+        } else {
+          listBuilder_.remove(index);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public org.sonar.batch.protocol.output.BatchOutput.ReportIssue.Builder getListBuilder(
+          int index) {
+        return getListFieldBuilder().getBuilder(index);
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public org.sonar.batch.protocol.output.BatchOutput.ReportIssueOrBuilder getListOrBuilder(
+          int index) {
+        if (listBuilder_ == null) {
+          return list_.get(index);  } else {
+          return listBuilder_.getMessageOrBuilder(index);
+        }
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public java.util.List<? extends org.sonar.batch.protocol.output.BatchOutput.ReportIssueOrBuilder> 
+           getListOrBuilderList() {
+        if (listBuilder_ != null) {
+          return listBuilder_.getMessageOrBuilderList();
+        } else {
+          return java.util.Collections.unmodifiableList(list_);
+        }
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public org.sonar.batch.protocol.output.BatchOutput.ReportIssue.Builder addListBuilder() {
+        return getListFieldBuilder().addBuilder(
+            org.sonar.batch.protocol.output.BatchOutput.ReportIssue.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public org.sonar.batch.protocol.output.BatchOutput.ReportIssue.Builder addListBuilder(
+          int index) {
+        return getListFieldBuilder().addBuilder(
+            index, org.sonar.batch.protocol.output.BatchOutput.ReportIssue.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .ReportIssue list = 2;</code>
+       */
+      public java.util.List<org.sonar.batch.protocol.output.BatchOutput.ReportIssue.Builder> 
+           getListBuilderList() {
+        return getListFieldBuilder().getBuilderList();
+      }
+      private com.google.protobuf.RepeatedFieldBuilder<
+          org.sonar.batch.protocol.output.BatchOutput.ReportIssue, org.sonar.batch.protocol.output.BatchOutput.ReportIssue.Builder, org.sonar.batch.protocol.output.BatchOutput.ReportIssueOrBuilder> 
+          getListFieldBuilder() {
+        if (listBuilder_ == null) {
+          listBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
+              org.sonar.batch.protocol.output.BatchOutput.ReportIssue, org.sonar.batch.protocol.output.BatchOutput.ReportIssue.Builder, org.sonar.batch.protocol.output.BatchOutput.ReportIssueOrBuilder>(
+                  list_,
+                  ((bitField0_ & 0x00000002) == 0x00000002),
+                  getParentForChildren(),
+                  isClean());
+          list_ = null;
+        }
+        return listBuilder_;
+      }
+
+      // @@protoc_insertion_point(builder_scope:ReportIssues)
+    }
+
+    static {
+      defaultInstance = new ReportIssues(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:ReportIssues)
+  }
+
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_ReportMetadata_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_ReportMetadata_fieldAccessorTable;
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_ReportComponent_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_ReportComponent_fieldAccessorTable;
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_ReportIssue_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_ReportIssue_fieldAccessorTable;
+  private static final com.google.protobuf.Descriptors.Descriptor
+    internal_static_ReportIssues_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_ReportIssues_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\022batch_output.proto\032\017constants.proto\"X\n" +
+      "\016ReportMetadata\022\025\n\ranalysis_date\030\001 \001(\003\022\023" +
+      "\n\013project_key\030\002 \001(\t\022\032\n\022root_component_re" +
+      "f\030\003 \001(\005\"\262\001\n\017ReportComponent\022\013\n\003ref\030\001 \001(\005" +
+      "\022\014\n\004path\030\002 \001(\t\022\014\n\004name\030\003 \001(\t\022\034\n\004type\030\004 \001" +
+      "(\0162\016.ComponentType\022\017\n\007is_test\030\005 \001(\010\022\020\n\010l" +
+      "anguage\030\006 \001(\t\022\022\n\nchild_refs\030\007 \003(\005\022\023\n\013sna" +
+      "pshot_id\030\010 \001(\005\022\014\n\004uuid\030\t \001(\t\"\240\004\n\013ReportI" +
+      "ssue\022\027\n\017rule_repository\030\001 \001(\t\022\020\n\010rule_ke" +
+      "y\030\002 \001(\t\022\014\n\004line\030\003 \001(\005\022\013\n\003msg\030\004 \001(\t\022\033\n\010se",
+      "verity\030\005 \001(\0162\t.Severity\022\014\n\004tags\030\006 \003(\t\022\025\n" +
+      "\reffort_to_fix\030\007 \001(\001\022\016\n\006is_new\030\010 \001(\010\022\014\n\004" +
+      "uuid\030\t \001(\t\022\027\n\017debt_in_minutes\030\n \001(\003\022\022\n\nr" +
+      "esolution\030\013 \001(\t\022\016\n\006status\030\014 \001(\t\022\020\n\010check" +
+      "sum\030\r \001(\t\022\027\n\017manual_severity\030\016 \001(\010\022\020\n\010re" +
+      "porter\030\017 \001(\t\022\020\n\010assignee\030\020 \001(\t\022\027\n\017action" +
+      "_plan_key\030\021 \001(\t\022\022\n\nattributes\030\022 \001(\t\022\024\n\014a" +
+      "uthor_login\030\023 \001(\t\022\025\n\rcreation_date\030\024 \001(\003" +
+      "\022\022\n\nclose_date\030\025 \001(\003\022\023\n\013update_date\030\026 \001(" +
+      "\003\022\023\n\013selected_at\030\027 \001(\003\022\023\n\013diff_fields\030\030 ",
+      "\001(\t\022\022\n\nis_changed\030\031 \001(\010\022\036\n\026must_send_not" +
+      "ification\030\032 \001(\010\"A\n\014ReportIssues\022\025\n\rcompo" +
+      "nent_ref\030\001 \001(\005\022\032\n\004list\030\002 \003(\0132\014.ReportIss" +
+      "ueB#\n\037org.sonar.batch.protocol.outputH\001"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+        new com.google.protobuf.Descriptors.FileDescriptor.    InternalDescriptorAssigner() {
+          public com.google.protobuf.ExtensionRegistry assignDescriptors(
+              com.google.protobuf.Descriptors.FileDescriptor root) {
+            descriptor = root;
+            return null;
+          }
+        };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+          org.sonar.batch.protocol.Constants.getDescriptor(),
+        }, assigner);
+    internal_static_ReportMetadata_descriptor =
+      getDescriptor().getMessageTypes().get(0);
+    internal_static_ReportMetadata_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_ReportMetadata_descriptor,
+        new java.lang.String[] { "AnalysisDate", "ProjectKey", "RootComponentRef", });
+    internal_static_ReportComponent_descriptor =
+      getDescriptor().getMessageTypes().get(1);
+    internal_static_ReportComponent_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_ReportComponent_descriptor,
+        new java.lang.String[] { "Ref", "Path", "Name", "Type", "IsTest", "Language", "ChildRefs", "SnapshotId", "Uuid", });
+    internal_static_ReportIssue_descriptor =
+      getDescriptor().getMessageTypes().get(2);
+    internal_static_ReportIssue_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_ReportIssue_descriptor,
+        new java.lang.String[] { "RuleRepository", "RuleKey", "Line", "Msg", "Severity", "Tags", "EffortToFix", "IsNew", "Uuid", "DebtInMinutes", "Resolution", "Status", "Checksum", "ManualSeverity", "Reporter", "Assignee", "ActionPlanKey", "Attributes", "AuthorLogin", "CreationDate", "CloseDate", "UpdateDate", "SelectedAt", "DiffFields", "IsChanged", "MustSendNotification", });
+    internal_static_ReportIssues_descriptor =
+      getDescriptor().getMessageTypes().get(3);
+    internal_static_ReportIssues_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_ReportIssues_descriptor,
+        new java.lang.String[] { "ComponentRef", "List", });
+    org.sonar.batch.protocol.Constants.getDescriptor();
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/ProtobufUtil.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/ProtobufUtil.java
new file mode 100644 (file)
index 0000000..8d7d5a6
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.protocol;
+
+import com.google.protobuf.Message;
+import com.google.protobuf.Parser;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class ProtobufUtil {
+  private ProtobufUtil() {
+    // only static stuff
+  }
+
+  public static <T extends Message> T readFile(File file, Parser<T> parser) {
+    try (InputStream input = new BufferedInputStream(new FileInputStream(file))) {
+      return parser.parseFrom(input);
+    } catch (IOException e) {
+      throw new IllegalStateException("Failed to read file: " + file, e);
+    }
+  }
+
+  public static void writeToFile(Message message, File toFile) {
+    try (OutputStream out = new BufferedOutputStream(new FileOutputStream(toFile, false))) {
+      message.writeTo(out);
+    } catch (IOException e) {
+      throw new IllegalStateException("Unable to write protocol buffer data to file " + toFile, e);
+    }
+  }
+}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchOutputReader.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchOutputReader.java
new file mode 100644 (file)
index 0000000..fe5799b
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.protocol.output;
+
+import org.sonar.batch.protocol.ProtobufUtil;
+
+import javax.annotation.CheckForNull;
+import java.io.File;
+import java.util.Collections;
+
+public class BatchOutputReader {
+
+  private final FileStructure fileStructure;
+
+  public BatchOutputReader(File dir) {
+    this.fileStructure = new FileStructure(dir);
+  }
+
+  public BatchOutput.ReportMetadata readMetadata() {
+    File file = fileStructure.metadataFile();
+    if (!file.exists() || !file.isFile()) {
+      throw new IllegalStateException("Metadata file is missing in analysis report: " + file);
+    }
+    return ProtobufUtil.readFile(file, BatchOutput.ReportMetadata.PARSER);
+  }
+
+  @CheckForNull
+  public BatchOutput.ReportComponent readComponent(int componentRef) {
+    File file = fileStructure.fileFor(FileStructure.Domain.COMPONENT, componentRef);
+    if (file.exists() && file.isFile()) {
+      return ProtobufUtil.readFile(file, BatchOutput.ReportComponent.PARSER);
+    }
+    return null;
+  }
+
+  public Iterable<BatchOutput.ReportIssue> readComponentIssues(int componentRef) {
+    File file = fileStructure.fileFor(FileStructure.Domain.ISSUES, componentRef);
+    if (file.exists() && file.isFile()) {
+      // all the issues are loaded in memory
+      BatchOutput.ReportIssues issues = ProtobufUtil.readFile(file, BatchOutput.ReportIssues.PARSER);
+      return issues.getListList();
+    }
+    return Collections.emptyList();
+  }
+}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchOutputWriter.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchOutputWriter.java
new file mode 100644 (file)
index 0000000..746ff60
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.protocol.output;
+
+import org.sonar.batch.protocol.ProtobufUtil;
+
+import java.io.File;
+
+public class BatchOutputWriter {
+
+  private final FileStructure fileStructure;
+
+  public BatchOutputWriter(File dir) {
+    if (!dir.exists() && !dir.mkdirs()) {
+      throw new IllegalStateException("Unable to create directory: " + dir);
+    }
+    this.fileStructure = new FileStructure(dir);
+  }
+
+  FileStructure getFileStructure() {
+    return fileStructure;
+  }
+
+  public boolean hasComponentData(FileStructure.Domain domain, int componentRef) {
+    File file = fileStructure.fileFor(domain, componentRef);
+    return file.exists() && file.isFile();
+  }
+
+  /**
+   * Metadata is mandatory
+   */
+  public void writeMetadata(BatchOutput.ReportMetadata metadata) {
+    ProtobufUtil.writeToFile(metadata, fileStructure.metadataFile());
+  }
+
+  public void writeComponent(BatchOutput.ReportComponent component) {
+    File file = fileStructure.fileFor(FileStructure.Domain.COMPONENT, component.getRef());
+    ProtobufUtil.writeToFile(component, file);
+  }
+
+  public void writeComponentIssues(int componentRef, Iterable<BatchOutput.ReportIssue> issues) {
+    BatchOutput.ReportIssues.Builder issuesBuilder = BatchOutput.ReportIssues.newBuilder();
+    issuesBuilder.setComponentRef(componentRef);
+    issuesBuilder.addAllList(issues);
+    File file = fileStructure.fileFor(FileStructure.Domain.ISSUES, componentRef);
+    ProtobufUtil.writeToFile(issuesBuilder.build(), file);
+  }
+}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java
new file mode 100644 (file)
index 0000000..5e2d51b
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.protocol.output;
+
+import java.io.File;
+
+/**
+ * Structure of files in the zipped report
+ */
+public class FileStructure {
+
+  public static enum Domain {
+    ISSUES("issues-"), COMPONENT("component-");
+
+    private final String filePrefix;
+
+    Domain(String filePrefix) {
+      this.filePrefix = filePrefix;
+    }
+  }
+
+  private final File dir;
+
+  FileStructure(File dir) {
+    if (!dir.exists() || !dir.isDirectory()) {
+      throw new IllegalArgumentException("Directory of analysis report does not exist: " + dir);
+    }
+    this.dir = dir;
+  }
+
+  public File metadataFile() {
+    return new File(dir, "metadata.pb");
+  }
+
+  public File fileFor(Domain domain, int componentRef) {
+    return new File(dir, domain.filePrefix + componentRef + ".pb");
+  }
+
+}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/ReportHelper.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/ReportHelper.java
deleted file mode 100644 (file)
index 3bb134d..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.protocol.output;
-
-import com.google.gson.Gson;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-import org.apache.commons.io.Charsets;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.sonar.batch.protocol.GsonHelper;
-import org.sonar.batch.protocol.output.component.ReportComponents;
-import org.sonar.batch.protocol.output.issue.ReportIssue;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-public class ReportHelper {
-
-  private static final String COMPONENTS_JSON = "components.json";
-  private final File reportRootDir;
-  private final Gson gson = GsonHelper.create();
-
-  private ReportHelper(File reportRootDir) {
-    this.reportRootDir = reportRootDir;
-  }
-
-  public static ReportHelper create(File workDirectory) {
-    if (!workDirectory.exists() && !workDirectory.mkdirs()) {
-      throw new IllegalStateException("Unable to create directory " + workDirectory);
-    }
-    return new ReportHelper(workDirectory);
-  }
-
-  public File reportRootDir() {
-    return reportRootDir;
-  }
-
-  public void saveComponents(ReportComponents components) {
-    File resourcesFile = new File(reportRootDir, COMPONENTS_JSON);
-    try {
-      FileUtils.write(resourcesFile, components.toJson());
-    } catch (IOException e) {
-      throw new IllegalStateException("Unable to write components", e);
-    }
-  }
-
-  public void saveIssues(long componentBatchId, Iterable<ReportIssue> issues) {
-    File issuesFile = getIssuesFile(componentBatchId);
-    try (OutputStreamWriter out = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(issuesFile)), "UTF-8")) {
-
-      JsonWriter writer = new JsonWriter(out);
-      writer.setIndent("  ");
-      writer.beginArray();
-      for (ReportIssue reportIssue : issues) {
-        gson.toJson(reportIssue, ReportIssue.class, writer);
-      }
-      writer.endArray();
-      writer.close();
-    } catch (IOException e) {
-      throw new IllegalStateException("Unable to save issues", e);
-    }
-  }
-
-  private File getIssuesFile(long componentBatchId) {
-    return new File(getComponentFolder(componentBatchId), "issues-" + componentBatchId + ".json");
-  }
-
-  private File getComponentFolder(long componentBatchId) {
-    File folder = new File(reportRootDir, Long.toString(componentBatchId));
-    if (!folder.exists() && !folder.mkdir()) {
-      throw new IllegalStateException("Unable to create directory " + folder);
-    }
-    return folder;
-  }
-
-  public ReportComponents getComponents() {
-    File file = new File(reportRootDir, COMPONENTS_JSON);
-
-    try (InputStream resourcesStream = new FileInputStream(file)) {
-      String json = IOUtils.toString(resourcesStream);
-      return ReportComponents.fromJson(json);
-    } catch (IOException e) {
-      throw new IllegalStateException("Failed to read issues", e);
-    }
-  }
-
-  public Iterable<ReportIssue> getIssues(final long componentBatchId) {
-
-    return new Iterable<ReportIssue>() {
-      @Override
-      public Iterator<ReportIssue> iterator() {
-        return new ReportIssueIterator(getIssuesFile(componentBatchId));
-      }
-    };
-  }
-
-  private final class ReportIssueIterator implements Iterator<ReportIssue> {
-
-    private JsonReader reader;
-
-    public ReportIssueIterator(File issuesFile) {
-      try {
-        reader = new JsonReader(new InputStreamReader(new BufferedInputStream(new FileInputStream(issuesFile)), Charsets.UTF_8));
-        reader.beginArray();
-      } catch (IOException e) {
-        throw new IllegalStateException("Unable to read " + issuesFile, e);
-      }
-    }
-
-    @Override
-    public boolean hasNext() {
-      try {
-        if (reader.hasNext()) {
-          return true;
-        }
-        reader.endArray();
-        reader.close();
-        return false;
-      } catch (IOException e) {
-        IOUtils.closeQuietly(reader);
-        throw new IllegalStateException("Unable to iterate over JSON file ", e);
-      }
-    }
-
-    @Override
-    public ReportIssue next() {
-      try {
-        if (!reader.hasNext()) {
-          throw new NoSuchElementException();
-        }
-      } catch (IOException e) {
-        throw new IllegalStateException("Unable to iterate over JSON file ", e);
-      }
-      return gson.fromJson(reader, ReportIssue.class);
-    }
-
-    @Override
-    public void remove() {
-      throw new UnsupportedOperationException("remove");
-    }
-  }
-
-}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/component/ReportComponent.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/component/ReportComponent.java
deleted file mode 100644 (file)
index 37768d8..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.protocol.output.component;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-public class ReportComponent {
-
-  public enum Type {
-    PRJ,
-    MOD,
-    DIR,
-    FIL,
-    VIEW,
-    SUBVIEW
-  }
-
-  private long batchId;
-  private int id;
-  private int snapshotId;
-  private String path;
-  private String name;
-  private String uuid;
-  private Type type;
-  // Only for files
-  private Boolean isTest;
-  private String languageKey;
-
-  private Collection<ReportComponent> children = new ArrayList<ReportComponent>();
-
-  public ReportComponent setBatchId(long batchId) {
-    this.batchId = batchId;
-    return this;
-  }
-
-  public long batchId() {
-    return batchId;
-  }
-
-  public ReportComponent setId(int id) {
-    this.id = id;
-    return this;
-  }
-
-  public int id() {
-    return id;
-  }
-
-  public ReportComponent setSnapshotId(int snapshotId) {
-    this.snapshotId = snapshotId;
-    return this;
-  }
-
-  public int snapshotId() {
-    return snapshotId;
-  }
-
-  public ReportComponent setPath(String path) {
-    this.path = path;
-    return this;
-  }
-
-  public String path() {
-    return path;
-  }
-
-  public ReportComponent setUuid(String s) {
-    this.uuid = s;
-    return this;
-  }
-
-  public String uuid() {
-    return uuid;
-  }
-
-  public ReportComponent setName(@Nullable String name) {
-    this.name = name;
-    return this;
-  }
-
-  /**
-   * @return null for files and directories since it is the same as the path
-   */
-  @CheckForNull
-  public String name() {
-    return name;
-  }
-
-  public ReportComponent setType(Type type) {
-    this.type = type;
-    return this;
-  }
-
-  public Type type() {
-    return type;
-  }
-
-  public ReportComponent setTest(@Nullable Boolean isTest) {
-    this.isTest = isTest;
-    return this;
-  }
-
-  /**
-   * @return null when not a file
-   */
-  @CheckForNull
-  public Boolean isTest() {
-    return isTest;
-  }
-
-  public ReportComponent setLanguageKey(@Nullable String languageKey) {
-    this.languageKey = languageKey;
-    return this;
-  }
-
-  /**
-   * @return null when not a file
-   */
-  @CheckForNull
-  public String languageKey() {
-    return languageKey;
-  }
-
-  public ReportComponent addChild(ReportComponent child) {
-    this.children.add(child);
-    return this;
-  }
-
-  public Collection<ReportComponent> children() {
-    return children;
-  }
-
-}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/component/ReportComponents.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/component/ReportComponents.java
deleted file mode 100644 (file)
index 5ee00ee..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.protocol.output.component;
-
-import org.sonar.batch.protocol.GsonHelper;
-
-import java.util.Date;
-
-public class ReportComponents {
-
-  private Date analysisDate;
-
-  private ReportComponent root;
-
-  public void setAnalysisDate(Date analysisDate) {
-    this.analysisDate = analysisDate;
-  }
-
-  public Date analysisDate() {
-    return analysisDate;
-  }
-
-  public ReportComponents setRoot(ReportComponent r) {
-    this.root = r;
-    return this;
-  }
-
-  public ReportComponent root() {
-    return root;
-  }
-
-  public String toJson() {
-    return GsonHelper.create().toJson(this);
-  }
-
-  public static ReportComponents fromJson(String json) {
-    return GsonHelper.create().fromJson(json, ReportComponents.class);
-  }
-
-}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/component/package-info.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/component/package-info.java
deleted file mode 100644 (file)
index 7e8017a..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.batch.protocol.output.component;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/issue/ReportIssue.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/issue/ReportIssue.java
deleted file mode 100644 (file)
index 23d62db..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.protocol.output.issue;
-
-import javax.annotation.Nullable;
-
-import java.util.Collection;
-import java.util.Date;
-
-public class ReportIssue {
-
-  private Long componentBatchId;
-  private String ruleKey;
-  private String ruleRepo;
-  private Integer line;
-  private String message;
-  private Double effortToFix;
-  private String severity;
-  private Collection<String> tags;
-
-  // Temporary fields that should be removed when aggregation/issue tracking is done by computation
-  private boolean isNew;
-  private String key;
-  private Long debtInMinutes;
-  private String resolution;
-  private String status;
-  private String checksum;
-  private boolean manualSeverity;
-  private String reporter;
-  private String assignee;
-  private String actionPlanKey;
-  private String attributes;
-  private String authorLogin;
-  private Date creationDate;
-  private Date closeDate;
-  private Date updateDate;
-  private Long selectedAt;
-  private String diffFields;
-  private boolean isChanged;
-  private boolean mustSendNotification;
-
-
-  public ReportIssue setKey(String key) {
-    this.key = key;
-    return this;
-  }
-
-  public String key() {
-    return key;
-  }
-
-  public ReportIssue setComponentBatchId(@Nullable Long resourceBatchId) {
-    this.componentBatchId = resourceBatchId;
-    return this;
-  }
-
-  public Long componentBatchId() {
-    return componentBatchId;
-  }
-
-  public ReportIssue setNew(boolean isNew) {
-    this.isNew = isNew;
-    return this;
-  }
-
-  public boolean isNew() {
-    return isNew;
-  }
-
-  public ReportIssue setLine(Integer line) {
-    this.line = line;
-    return this;
-  }
-
-  public Integer line() {
-    return line;
-  }
-
-  public ReportIssue setMessage(String message) {
-    this.message = message;
-    return this;
-  }
-
-  public String message() {
-    return message;
-  }
-
-  public ReportIssue setEffortToFix(Double effortToFix) {
-    this.effortToFix = effortToFix;
-    return this;
-  }
-
-  public Double effortToFix() {
-    return effortToFix;
-  }
-
-  public ReportIssue setDebt(Long debtInMinutes) {
-    this.debtInMinutes = debtInMinutes;
-    return this;
-  }
-
-  public Long debt() {
-    return debtInMinutes;
-  }
-
-  public ReportIssue setResolution(String resolution) {
-    this.resolution = resolution;
-    return this;
-  }
-
-  public String resolution() {
-    return resolution;
-  }
-
-  public ReportIssue setStatus(String status) {
-    this.status = status;
-    return this;
-  }
-
-  public String status() {
-    return status;
-  }
-
-  public ReportIssue setSeverity(String severity) {
-    this.severity = severity;
-    return this;
-  }
-
-  public String severity() {
-    return severity;
-  }
-
-  public ReportIssue setChecksum(String checksum) {
-    this.checksum = checksum;
-    return this;
-  }
-
-  public String checksum() {
-    return checksum;
-  }
-
-  public ReportIssue setManualSeverity(boolean manualSeverity) {
-    this.manualSeverity = manualSeverity;
-    return this;
-  }
-
-  public boolean isManualSeverity() {
-    return manualSeverity;
-  }
-
-  public ReportIssue setReporter(String reporter) {
-    this.reporter = reporter;
-    return this;
-  }
-
-  public String reporter() {
-    return reporter;
-  }
-
-  public ReportIssue setAssignee(String assignee) {
-    this.assignee = assignee;
-    return this;
-  }
-
-  public String assignee() {
-    return assignee;
-  }
-
-  public Collection<String> tags() {
-    return tags;
-  }
-
-  public ReportIssue setTags(Collection<String> s) {
-    this.tags = s;
-    return this;
-  }
-
-  public ReportIssue setRuleKey(String ruleRepo, String ruleKey) {
-    this.ruleRepo = ruleRepo;
-    this.ruleKey = ruleKey;
-    return this;
-  }
-
-  public String ruleRepo() {
-    return ruleRepo;
-  }
-
-  public String ruleKey() {
-    return ruleKey;
-  }
-
-  public ReportIssue setActionPlanKey(String actionPlanKey) {
-    this.actionPlanKey = actionPlanKey;
-    return this;
-  }
-
-  public String actionPlanKey() {
-    return actionPlanKey;
-  }
-
-  public ReportIssue setAttributes(String attributes) {
-    this.attributes = attributes;
-    return this;
-  }
-
-  public String issueAttributes() {
-    return attributes;
-  }
-
-  public ReportIssue setAuthorLogin(String authorLogin) {
-    this.authorLogin = authorLogin;
-    return this;
-  }
-
-  public String authorLogin() {
-    return authorLogin;
-  }
-
-  public ReportIssue setCreationDate(Date creationDate) {
-    this.creationDate = creationDate;
-    return this;
-  }
-
-  public Date creationDate() {
-    return creationDate;
-  }
-
-  public ReportIssue setCloseDate(Date closeDate) {
-    this.closeDate = closeDate;
-    return this;
-  }
-
-  public Date closeDate() {
-    return closeDate;
-  }
-
-  public ReportIssue setUpdateDate(Date updateDate) {
-    this.updateDate = updateDate;
-    return this;
-  }
-
-  public Date updateDate() {
-    return updateDate;
-  }
-
-  public ReportIssue setSelectedAt(Long selectedAt) {
-    this.selectedAt = selectedAt;
-    return this;
-  }
-
-  public Long selectedAt() {
-    return selectedAt;
-  }
-
-  public ReportIssue setDiffFields(@Nullable String diffFields) {
-    this.diffFields = diffFields;
-    return this;
-  }
-
-  public String diffFields() {
-    return diffFields;
-  }
-
-  public ReportIssue setChanged(boolean isChanged) {
-    this.isChanged = isChanged;
-    return this;
-  }
-
-  public boolean isChanged() {
-    return isChanged;
-  }
-
-  public ReportIssue setMustSendNotification(boolean mustSendNotification) {
-    this.mustSendNotification = mustSendNotification;
-    return this;
-  }
-
-  public boolean mustSendNotifications() {
-    return mustSendNotification;
-  }
-}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/issue/package-info.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/issue/package-info.java
deleted file mode 100644 (file)
index 444216d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.batch.protocol.output.issue;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-batch-protocol/src/main/protobuf/batch_output.proto b/sonar-batch-protocol/src/main/protobuf/batch_output.proto
new file mode 100644 (file)
index 0000000..4b26c98
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+    SonarQube, open source software quality management tool.
+    Copyright (C) 2008-2015 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.
+*/
+
+/*
+Notes
+
+  - "required" fields are not used as recommended by Google to keep forward-compatibility:
+    https://developers.google.com/protocol-buffers/docs/proto#simple
+
+  - this is beta version of specification. It will evolve during next releases and is
+    not forward-compatible yet.
+
+  - the related Java files are not generated during build. Indeed the existing protoc maven
+    plugins require protobuf to be installed on boxes. That means that generated Java files
+    are updated and committed for each change (see src/main/gen-java).
+*/
+
+
+import "constants.proto";
+
+option java_package = "org.sonar.batch.protocol.output";
+option optimize_for = SPEED;
+
+message ReportMetadata {
+  optional int64 analysis_date = 1;
+  optional string project_key = 2;
+  optional int32 root_component_ref = 3;
+}
+
+message ReportComponent {
+  optional int32 ref = 1;
+  optional string path = 2;
+  optional string name = 3;
+  optional ComponentType type = 4;
+  optional bool is_test = 5;
+  optional string language = 6;
+  repeated int32 child_refs = 7;
+
+  // temporary fields during development of computation stack
+  optional int32 snapshot_id = 8;
+  optional string uuid = 9;
+}
+
+message ReportIssue {
+    optional string rule_repository = 1;
+    optional string rule_key = 2;
+    optional int32 line = 3;
+    optional string msg = 4;
+    optional Severity severity = 5;
+    repeated string tags = 6;
+
+    // temporary fields during development of computation stack
+    optional double effort_to_fix = 7;
+    optional bool is_new = 8;
+    optional string uuid = 9;
+    optional int64 debt_in_minutes = 10;
+    optional string resolution = 11;
+    optional string status = 12;
+    optional string checksum = 13;
+    optional bool manual_severity = 14;
+    optional string reporter = 15;
+    optional string assignee = 16;
+    optional string action_plan_key = 17;
+    optional string attributes = 18;
+    optional string author_login = 19;
+    optional int64 creation_date = 20;
+    optional int64 close_date = 21;
+    optional int64 update_date = 22;
+    optional int64 selected_at = 23;
+    optional string diff_fields = 24;
+    optional bool is_changed = 25;
+    optional bool must_send_notification = 26;
+}
+
+message ReportIssues {
+    optional int32 component_ref = 1;
+    repeated ReportIssue list = 2;
+}
diff --git a/sonar-batch-protocol/src/main/protobuf/constants.proto b/sonar-batch-protocol/src/main/protobuf/constants.proto
new file mode 100644 (file)
index 0000000..3cbc886
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+    SonarQube, open source software quality management tool.
+    Copyright (C) 2008-2015 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.
+*/
+
+option java_package = "org.sonar.batch.protocol";
+option optimize_for = SPEED;
+
+enum Severity {
+  INFO = 0;
+  MINOR = 1;
+  MAJOR = 2;
+  CRITICAL = 3;
+  BLOCKER = 4;
+}
+
+enum ComponentType {
+  PROJECT = 0;
+  MODULE = 1;
+  DIRECTORY = 2;
+  FILE = 3;
+  VIEW = 4;
+  SUBVIEW = 5;
+}
diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/ProtobufUtilTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/ProtobufUtilTest.java
new file mode 100644 (file)
index 0000000..8084bb2
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.protocol;
+
+import org.junit.Test;
+import org.sonar.test.TestUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ProtobufUtilTest {
+
+  @Test
+  public void only_utils() throws Exception {
+    assertThat(TestUtils.hasOnlyPrivateConstructors(ProtobufUtil.class));
+  }
+
+}
diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchOutputReaderTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchOutputReaderTest.java
new file mode 100644 (file)
index 0000000..930e3e3
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.protocol.output;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.util.Arrays;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class BatchOutputReaderTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Test
+  public void create_dir_if_does_not_exist() throws Exception {
+    File dir = temp.newFolder();
+
+    initFiles(dir);
+
+    BatchOutputReader reader = new BatchOutputReader(dir);
+    assertThat(reader.readMetadata().getAnalysisDate()).isEqualTo(15000000L);
+    assertThat(reader.readComponentIssues(1)).hasSize(1);
+    assertThat(reader.readComponentIssues(200)).isEmpty();
+    assertThat(reader.readComponent(1).getUuid()).isEqualTo("UUID_A");
+    assertThat(reader.readComponent(200)).isNull();
+
+  }
+
+  private void initFiles(File dir) {
+    BatchOutputWriter writer = new BatchOutputWriter(dir);
+
+    BatchOutput.ReportMetadata.Builder metadata = BatchOutput.ReportMetadata.newBuilder()
+      .setAnalysisDate(15000000L)
+      .setProjectKey("PROJECT_A")
+      .setRootComponentRef(1);
+    writer.writeMetadata(metadata.build());
+
+    BatchOutput.ReportComponent.Builder component = BatchOutput.ReportComponent.newBuilder()
+      .setRef(1)
+      .setUuid("UUID_A");
+    writer.writeComponent(component.build());
+
+    BatchOutput.ReportIssue issue = BatchOutput.ReportIssue.newBuilder()
+      .setUuid("ISSUE_A")
+      .setLine(50)
+      .build();
+
+    writer.writeComponentIssues(1, Arrays.asList(issue));
+  }
+
+  @Test
+  public void readMetadata() throws Exception {
+
+  }
+}
diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchOutputWriterTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/BatchOutputWriterTest.java
new file mode 100644 (file)
index 0000000..9261f1b
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.protocol.output;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.batch.protocol.Constants;
+import org.sonar.batch.protocol.ProtobufUtil;
+
+import java.io.File;
+import java.util.Arrays;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class BatchOutputWriterTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Test
+  public void create_dir_if_does_not_exist() throws Exception {
+    File dir = temp.newFolder();
+    FileUtils.deleteQuietly(dir);
+
+    new BatchOutputWriter(dir);
+
+    assertThat(dir).isDirectory().exists();
+  }
+
+  @Test
+  public void write_metadata() throws Exception {
+    File dir = temp.newFolder();
+    BatchOutputWriter writer = new BatchOutputWriter(dir);
+    BatchOutput.ReportMetadata.Builder metadata = BatchOutput.ReportMetadata.newBuilder()
+      .setAnalysisDate(15000000L)
+      .setProjectKey("PROJECT_A")
+      .setRootComponentRef(1);
+    writer.writeMetadata(metadata.build());
+
+    BatchOutput.ReportMetadata read = ProtobufUtil.readFile(writer.getFileStructure().metadataFile(), BatchOutput.ReportMetadata.PARSER);
+    assertThat(read.getAnalysisDate()).isEqualTo(15000000L);
+    assertThat(read.getProjectKey()).isEqualTo("PROJECT_A");
+    assertThat(read.getRootComponentRef()).isEqualTo(1);
+  }
+
+  @Test
+  public void write_component() throws Exception {
+    File dir = temp.newFolder();
+    BatchOutputWriter writer = new BatchOutputWriter(dir);
+
+    // no data yet
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 1)).isFalse();
+
+    // write data
+    BatchOutput.ReportComponent.Builder component = BatchOutput.ReportComponent.newBuilder()
+      .setRef(1)
+      .setLanguage("java")
+      .setPath("src/Foo.java")
+      .setUuid("UUID_A")
+      .setType(Constants.ComponentType.FILE)
+      .setIsTest(false)
+      .addChildRefs(5)
+      .addChildRefs(42);
+    writer.writeComponent(component.build());
+
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 1)).isTrue();
+    File file = writer.getFileStructure().fileFor(FileStructure.Domain.COMPONENT, 1);
+    assertThat(file).exists().isFile();
+    BatchOutput.ReportComponent read = ProtobufUtil.readFile(file, BatchOutput.ReportComponent.PARSER);
+    assertThat(read.getRef()).isEqualTo(1);
+    assertThat(read.getChildRefsList()).containsOnly(5, 42);
+    assertThat(read.hasName()).isFalse();
+    assertThat(read.getIsTest()).isFalse();
+    assertThat(read.getUuid()).isEqualTo("UUID_A");
+  }
+
+  @Test
+  public void write_issues() throws Exception {
+    File dir = temp.newFolder();
+    BatchOutputWriter writer = new BatchOutputWriter(dir);
+
+    // no data yet
+    assertThat(writer.hasComponentData(FileStructure.Domain.ISSUES, 1)).isFalse();
+
+    // write data
+    BatchOutput.ReportIssue issue = BatchOutput.ReportIssue.newBuilder()
+      .setUuid("ISSUE_A")
+      .setLine(50)
+      .setMsg("the message")
+      .build();
+
+    writer.writeComponentIssues(1, Arrays.asList(issue));
+
+    assertThat(writer.hasComponentData(FileStructure.Domain.ISSUES, 1)).isTrue();
+    File file = writer.getFileStructure().fileFor(FileStructure.Domain.ISSUES, 1);
+    assertThat(file).exists().isFile();
+    BatchOutput.ReportIssues read = ProtobufUtil.readFile(file, BatchOutput.ReportIssues.PARSER);
+    assertThat(read.getComponentRef()).isEqualTo(1);
+    assertThat(read.getListCount()).isEqualTo(1);
+  }
+}
diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/FileStructureTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/FileStructureTest.java
new file mode 100644 (file)
index 0000000..465e5a6
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.protocol.output;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+
+public class FileStructureTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Test
+  public void fail_if_dir_does_not_exist() throws Exception {
+    File dir = temp.newFolder();
+    FileUtils.deleteQuietly(dir);
+    try {
+      new FileStructure(dir);
+      fail();
+    } catch (IllegalArgumentException e) {
+      assertThat(e).hasMessageContaining("Directory of analysis report does not exist");
+    }
+  }
+
+  @Test
+  public void fail_if_invalid_dir() throws Exception {
+    // not a dir but a file
+    File dir = temp.newFile();
+    try {
+      new FileStructure(dir);
+      fail();
+    } catch (IllegalArgumentException e) {
+      assertThat(e).hasMessageContaining("Directory of analysis report does not exist");
+    }
+  }
+
+  @Test
+  public void locate_files() throws Exception {
+    File dir = temp.newFolder();
+    FileUtils.write(new File(dir, "metadata.pb"), "metadata content");
+    FileUtils.write(new File(dir, "issues-3.pb"), "issues of component 3");
+    FileUtils.write(new File(dir, "component-42.pb"), "details of component 42");
+
+    FileStructure structure = new FileStructure(dir);
+    assertThat(structure.metadataFile()).exists().isFile();
+    assertThat(structure.fileFor(FileStructure.Domain.COMPONENT, 42)).exists().isFile();
+    assertThat(structure.fileFor(FileStructure.Domain.ISSUES, 3)).exists().isFile();
+    assertThat(structure.fileFor(FileStructure.Domain.ISSUES, 42)).doesNotExist();
+  }
+}
diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/ReportHelperTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/ReportHelperTest.java
deleted file mode 100644 (file)
index d79fb5a..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.protocol.output;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.batch.protocol.output.component.ReportComponent;
-import org.sonar.batch.protocol.output.component.ReportComponents;
-import org.sonar.batch.protocol.output.issue.ReportIssue;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ReportHelperTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Test
-  public void createAndRead() throws IOException {
-    ReportHelper helper = ReportHelper.create(temp.newFolder());
-
-    helper.saveComponents(new ReportComponents().setRoot(new ReportComponent().setBatchId(1L)));
-
-    helper.saveIssues(1L, Arrays.asList(new ReportIssue().setRuleKey("foo", "bar")));
-
-    assertThat(new File(helper.reportRootDir(), "components.json")).exists();
-    assertThat(new File(helper.reportRootDir(), "1/issues-1.json")).exists();
-
-    assertThat(helper.getComponents().root().batchId()).isEqualTo(1L);
-    assertThat(helper.getIssues(1L)).hasSize(1);
-  }
-
-}
diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/component/ReportComponentsTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/component/ReportComponentsTest.java
deleted file mode 100644 (file)
index 0df08d6..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.protocol.output.component;
-
-import org.apache.commons.io.IOUtils;
-import org.junit.Test;
-import org.skyscreamer.jsonassert.JSONAssert;
-import org.sonar.batch.protocol.output.component.ReportComponent.Type;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ReportComponentsTest {
-
-  @Test
-  public void to_json() throws Exception {
-    ReportComponents res = new ReportComponents();
-    Date d = new SimpleDateFormat("dd/MM/yyyy").parse("12/12/2012");
-    res.setAnalysisDate(d);
-    ReportComponent root = new ReportComponent()
-      .setBatchId(1)
-      .setId(11)
-      .setName("Root project")
-      .setSnapshotId(111)
-      .setType(Type.PRJ);
-    ReportComponent module = new ReportComponent()
-      .setBatchId(2)
-      .setId(22)
-      .setName("Module")
-      .setSnapshotId(222)
-      .setPath("module1")
-      .setType(Type.MOD);
-    root.addChild(module);
-    ReportComponent dir = new ReportComponent()
-      .setBatchId(3)
-      .setId(33)
-      .setName("src")
-      .setSnapshotId(333)
-      .setPath("src")
-      .setType(Type.DIR);
-    module.addChild(dir);
-    ReportComponent file = new ReportComponent()
-      .setBatchId(4)
-      .setId(44)
-      .setName("Foo.java")
-      .setSnapshotId(444)
-      .setPath("Foo.java")
-      .setType(Type.FIL)
-      .setTest(true)
-      .setLanguageKey("java");
-    dir.addChild(file);
-    res.setRoot(root);
-
-    JSONAssert
-      .assertEquals(
-        IOUtils.toString(this.getClass().getResourceAsStream("ReportComponentsTest/expected.json"), "UTF-8"),
-        res.toJson(), true);
-  }
-
-  @Test
-  public void from_json() throws Exception {
-    ReportComponents res = ReportComponents
-      .fromJson(
-      IOUtils.toString(this.getClass().getResourceAsStream("ReportComponentsTest/expected.json"), "UTF-8"));
-
-    assertThat(res.analysisDate()).isEqualTo(new SimpleDateFormat("dd/MM/yyyy").parse("12/12/2012"));
-    ReportComponent root = res.root();
-    assertThat(root.batchId()).isEqualTo(1);
-    assertThat(root.id()).isEqualTo(11);
-    assertThat(root.name()).isEqualTo("Root project");
-    assertThat(root.snapshotId()).isEqualTo(111);
-    assertThat(root.path()).isNull();
-    assertThat(root.type()).isEqualTo(Type.PRJ);
-    assertThat(root.children()).hasSize(1);
-    assertThat(root.isTest()).isNull();
-    assertThat(root.languageKey()).isNull();
-
-  }
-}
diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/issue/ReportIssueTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/output/issue/ReportIssueTest.java
deleted file mode 100644 (file)
index 36770b2..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.protocol.output.issue;
-
-import org.junit.Test;
-
-import java.text.SimpleDateFormat;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ReportIssueTest {
-
-  @Test
-  public void testGetterSetter() throws Exception {
-    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
-    ReportIssue issue = new ReportIssue()
-      .setActionPlanKey("plan")
-      .setAssignee("assignee")
-      .setAuthorLogin("author")
-      .setChanged(true)
-      .setChecksum("checksum")
-      .setDebt(3L)
-      .setDiffFields("diff")
-      .setEffortToFix(2.0)
-      .setAttributes("attributes")
-      .setCloseDate(sdf.parse("11/12/2012"))
-      .setCreationDate(sdf.parse("12/12/2012"))
-      .setUpdateDate(sdf.parse("13/12/2012"))
-      .setKey("key")
-      .setLine(3)
-      .setManualSeverity(true)
-      .setMessage("message")
-      .setNew(true)
-      .setReporter("reporter")
-      .setResolution("resolution")
-      .setComponentBatchId(4L)
-      .setRuleKey("repo", "rule")
-      .setSelectedAt(234L)
-      .setSeverity("severity")
-      .setStatus("status");
-
-    assertThat(issue.actionPlanKey()).isEqualTo("plan");
-    assertThat(issue.assignee()).isEqualTo("assignee");
-    assertThat(issue.authorLogin()).isEqualTo("author");
-    assertThat(issue.isChanged()).isTrue();
-    assertThat(issue.checksum()).isEqualTo("checksum");
-    assertThat(issue.debt()).isEqualTo(3L);
-    assertThat(issue.diffFields()).isEqualTo("diff");
-    assertThat(issue.effortToFix()).isEqualTo(2.0);
-    assertThat(issue.issueAttributes()).isEqualTo("attributes");
-    assertThat(issue.closeDate()).isEqualTo(sdf.parse("11/12/2012"));
-    assertThat(issue.creationDate()).isEqualTo(sdf.parse("12/12/2012"));
-    assertThat(issue.updateDate()).isEqualTo(sdf.parse("13/12/2012"));
-    assertThat(issue.key()).isEqualTo("key");
-    assertThat(issue.line()).isEqualTo(3);
-    assertThat(issue.isManualSeverity()).isTrue();
-    assertThat(issue.message()).isEqualTo("message");
-    assertThat(issue.isNew()).isTrue();
-    assertThat(issue.reporter()).isEqualTo("reporter");
-    assertThat(issue.resolution()).isEqualTo("resolution");
-    assertThat(issue.componentBatchId()).isEqualTo(4L);
-    assertThat(issue.ruleRepo()).isEqualTo("repo");
-    assertThat(issue.ruleKey()).isEqualTo("rule");
-    assertThat(issue.selectedAt()).isEqualTo(234L);
-    assertThat(issue.severity()).isEqualTo("severity");
-    assertThat(issue.status()).isEqualTo("status");
-  }
-
-}
index 4d3479368d495a38f3585a44ba5ca3d8a0b6ac83..10d4b9d543e7ee3ff85a8d51bb26953d4dd7bf4c 100644 (file)
@@ -31,13 +31,13 @@ import java.util.Collection;
 
 public class BatchResource {
 
-  private final long batchId;
+  private final int batchId;
   private final Resource r;
   private Snapshot s;
   private final BatchResource parent;
   private final Collection<BatchResource> children = new ArrayList<BatchResource>();
 
-  public BatchResource(long batchId, Resource r, @Nullable BatchResource parent) {
+  public BatchResource(int batchId, Resource r, @Nullable BatchResource parent) {
     this.batchId = batchId;
     this.r = r;
     this.parent = parent;
@@ -46,7 +46,7 @@ public class BatchResource {
     }
   }
 
-  public long batchId() {
+  public int batchId() {
     return batchId;
   }
 
index 9330a21066f347fcdc6901018fca5fe79aa97767..f8f44fc7a3d9657b927e4ca142a1be3f4e01de04 100644 (file)
@@ -26,14 +26,15 @@ import org.sonar.api.resources.Resource;
 import org.sonar.api.resources.ResourceUtils;
 import org.sonar.batch.index.BatchResource;
 import org.sonar.batch.index.ResourceCache;
-import org.sonar.batch.protocol.output.ReportHelper;
-import org.sonar.batch.protocol.output.component.ReportComponent;
-import org.sonar.batch.protocol.output.component.ReportComponents;
+import org.sonar.batch.protocol.Constants;
+import org.sonar.batch.protocol.output.BatchOutput;
+import org.sonar.batch.protocol.output.BatchOutputWriter;
 
 import javax.annotation.CheckForNull;
 
-import java.io.IOException;
-
+/**
+ * Adds components and analysis metadata to output report
+ */
 public class ComponentsPublisher implements ReportPublisher {
 
   private final ResourceCache resourceCache;
@@ -45,37 +46,52 @@ public class ComponentsPublisher implements ReportPublisher {
   }
 
   @Override
-  public void export(ReportHelper reportHelper) throws IOException {
-    ReportComponents components = new ReportComponents();
+  public void publish(BatchOutputWriter writer) {
     BatchResource rootProject = resourceCache.get(reactor.getRoot().getKeyWithBranch());
-    components.setRoot(buildResourceForReport(rootProject));
-    components.setAnalysisDate(((Project) rootProject.resource()).getAnalysisDate());
-    reportHelper.saveComponents(components);
+    BatchOutput.ReportMetadata metadata = BatchOutput.ReportMetadata.newBuilder()
+      .setAnalysisDate(((Project) rootProject.resource()).getAnalysisDate().getTime())
+      .setProjectKey(((Project) rootProject.resource()).key())
+      .setRootComponentRef(rootProject.batchId())
+      .build();
+    writer.writeMetadata(metadata);
+    recursiveWriteComponent(rootProject, writer);
   }
 
-  private ReportComponent buildResourceForReport(BatchResource batchResource) {
+  private void recursiveWriteComponent(BatchResource batchResource, BatchOutputWriter writer) {
     Resource r = batchResource.resource();
-    Integer snapshotId = batchResource.snapshotId();
-    Integer id = r.getId();
-    ReportComponent result = new ReportComponent()
-      .setBatchId(batchResource.batchId())
-      .setSnapshotId(snapshotId != null ? snapshotId.intValue() : -1)
-      .setId(id != null ? id : -1)
-      .setName(getName(r))
-      .setPath(r.getPath())
-      .setUuid(r.getUuid())
-      .setType(getType(r))
-      .setLanguageKey(getLanguageKey(r))
-      .setTest(isTest(r));
+    BatchOutput.ReportComponent.Builder builder = BatchOutput.ReportComponent.newBuilder();
+
+    // non-null fields
+    builder.setRef(batchResource.batchId());
+    builder.setSnapshotId(batchResource.snapshotId());
+    builder.setUuid(r.getUuid());
+    builder.setType(getType(r));
+
+    // protocol buffers does not accept null values
+
+    if (ResourceUtils.isFile(r)) {
+      builder.setIsTest(ResourceUtils.isUnitTestClass(r));
+    }
+    String name = getName(r);
+    if (name != null) {
+      builder.setName(name);
+    }
+    String path = r.getPath();
+    if (path != null) {
+      builder.setPath(path);
+    }
+    String lang = getLanguageKey(r);
+    if (lang != null) {
+      builder.setLanguage(lang);
+    }
     for (BatchResource child : batchResource.children()) {
-      result.addChild(buildResourceForReport(child));
+      builder.addChildRefs(child.batchId());
     }
-    return result;
-  }
+    writer.writeComponent(builder.build());
 
-  @CheckForNull
-  private Boolean isTest(Resource r) {
-    return ResourceUtils.isFile(r) ? ResourceUtils.isUnitTestClass(r) : null;
+    for (BatchResource child : batchResource.children()) {
+      recursiveWriteComponent(child, writer);
+    }
   }
 
   @CheckForNull
@@ -90,21 +106,21 @@ public class ComponentsPublisher implements ReportPublisher {
     return (ResourceUtils.isFile(r) || ResourceUtils.isDirectory(r)) ? null : r.getName();
   }
 
-  private ReportComponent.Type getType(Resource r) {
+  private Constants.ComponentType getType(Resource r) {
     if (ResourceUtils.isFile(r)) {
-      return ReportComponent.Type.FIL;
+      return Constants.ComponentType.FILE;
     } else if (ResourceUtils.isDirectory(r)) {
-      return ReportComponent.Type.DIR;
+      return Constants.ComponentType.DIRECTORY;
     } else if (ResourceUtils.isModuleProject(r)) {
-      return ReportComponent.Type.MOD;
+      return Constants.ComponentType.MODULE;
     } else if (ResourceUtils.isRootProject(r)) {
-      return ReportComponent.Type.PRJ;
+      return Constants.ComponentType.PROJECT;
     } else if (ResourceUtils.isView(r)) {
-      return ReportComponent.Type.VIEW;
+      return Constants.ComponentType.VIEW;
     } else if (ResourceUtils.isSubview(r)) {
-      return ReportComponent.Type.SUBVIEW;
+      return Constants.ComponentType.SUBVIEW;
     }
-    throw new IllegalArgumentException("Unknow resource type: " + r);
+    throw new IllegalArgumentException("Unknown resource type: " + r);
   }
 
 }
index 20982cf594b2a24c4323865389f3ea1b74857b2b..9f4a2857c3a269b72919f4f30ba128196e79119a 100644 (file)
@@ -27,10 +27,13 @@ import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.batch.index.BatchResource;
 import org.sonar.batch.index.ResourceCache;
 import org.sonar.batch.issue.IssueCache;
-import org.sonar.batch.protocol.output.ReportHelper;
-import org.sonar.batch.protocol.output.issue.ReportIssue;
+import org.sonar.batch.protocol.Constants;
+import org.sonar.batch.protocol.output.BatchOutputWriter;
+import org.sonar.batch.protocol.output.BatchOutput;
 
-import java.io.IOException;
+import javax.annotation.Nullable;
+
+import java.util.Date;
 
 public class IssuesPublisher implements ReportPublisher {
 
@@ -43,51 +46,91 @@ public class IssuesPublisher implements ReportPublisher {
   }
 
   @Override
-  public void export(ReportHelper reportHelper) throws IOException {
+  public void publish(BatchOutputWriter writer) {
     for (BatchResource resource : resourceCache.all()) {
       Iterable<DefaultIssue> issues = issueCache.byComponent(resource.resource().getEffectiveKey());
-      reportHelper.saveIssues(resource.batchId(), Iterables.transform(issues, new Function<DefaultIssue, ReportIssue>() {
+      writer.writeComponentIssues(resource.batchId(), Iterables.transform(issues, new Function<DefaultIssue, BatchOutput.ReportIssue>() {
         @Override
-        public ReportIssue apply(DefaultIssue input) {
+        public BatchOutput.ReportIssue apply(DefaultIssue input) {
           return toReportIssue(input);
         }
       }));
     }
   }
 
-  private ReportIssue toReportIssue(DefaultIssue issue) {
-    BatchResource batchResource = resourceCache.get(issue.componentKey());
-    return new ReportIssue()
-      .setKey(issue.key())
-      .setComponentBatchId(batchResource != null ? batchResource.batchId() : null)
-      .setNew(issue.isNew())
-      .setLine(issue.line())
-      .setMessage(issue.message())
-      .setEffortToFix(issue.effortToFix())
-      .setDebt(issue.debtInMinutes())
-      .setResolution(issue.resolution())
-      .setStatus(issue.status())
-      .setSeverity(issue.severity())
-      .setChecksum(issue.checksum())
-      .setManualSeverity(issue.manualSeverity())
-      .setReporter(issue.reporter())
-      .setAssignee(issue.assignee())
-      .setRuleKey(issue.ruleKey().repository(), issue.ruleKey().rule())
-      .setActionPlanKey(issue.actionPlanKey())
-      .setAttributes(KeyValueFormat.format(issue.attributes()))
-      .setAuthorLogin(issue.authorLogin())
-      .setCreationDate(issue.creationDate())
-      .setCloseDate(issue.closeDate())
-      .setUpdateDate(issue.updateDate())
-      .setSelectedAt(issue.selectedAt())
-      .setDiffFields(toString(issue.currentChange()))
-      .setTags(issue.tags())
-      .setMustSendNotification(issue.mustSendNotifications())
-      .setChanged(issue.isChanged());
+  private BatchOutput.ReportIssue toReportIssue(DefaultIssue issue) {
+    BatchOutput.ReportIssue.Builder builder = BatchOutput.ReportIssue.newBuilder();
+
+    // non-null fields
+    builder.setUuid(issue.key());
+    builder.setIsNew(issue.isNew());
+    builder.setSeverity(Constants.Severity.valueOf(issue.severity()));
+    builder.setRuleRepository(issue.ruleKey().repository());
+    builder.setRuleKey(issue.ruleKey().rule());
+    builder.setAttributes(KeyValueFormat.format(issue.attributes()));
+    builder.addAllTags(issue.tags());
+    builder.setMustSendNotification(issue.mustSendNotifications());
+    builder.setIsChanged(issue.isChanged());
+
+    // nullable fields
+    Integer line = issue.line();
+    if (line != null) {
+      builder.setLine(line);
+    }
+    builder.setMsg(issue.message());
+    if (issue.effortToFix() != null) {
+      builder.setEffortToFix(issue.effortToFix());
+    }
+    if (issue.debtInMinutes() != null) {
+      builder.setDebtInMinutes(issue.debtInMinutes());
+    }
+    if (issue.resolution() != null) {
+      builder.setResolution(issue.resolution());
+    }
+    if (issue.status() != null) {
+      builder.setStatus(issue.status());
+    }
+    if (issue.checksum() != null) {
+      builder.setChecksum(issue.checksum());
+    }
+    builder.setManualSeverity(issue.manualSeverity());
+    if (issue.reporter() != null) {
+      builder.setReporter(issue.reporter());
+    }
+    if (issue.assignee() != null) {
+      builder.setAssignee(issue.assignee());
+    }
+    if (issue.actionPlanKey() != null) {
+      builder.setActionPlanKey(issue.actionPlanKey());
+    }
+    if (issue.authorLogin() != null) {
+      builder.setAuthorLogin(issue.authorLogin());
+    }
+    String diff = diffsToString(issue.currentChange());
+    if (diff != null) {
+      builder.setDiffFields(diff);
+    }
+    Date creationDate = issue.creationDate();
+    if (creationDate != null) {
+      builder.setCreationDate(creationDate.getTime());
+    }
+    Long selectedAt = issue.selectedAt();
+    if (selectedAt != null) {
+      builder.setSelectedAt(selectedAt);
+    }
+    Date closeDate = issue.closeDate();
+    if (closeDate != null) {
+      builder.setCloseDate(closeDate.getTime());
+    }
+    Date updateDate = issue.updateDate();
+    if (updateDate != null) {
+      builder.setUpdateDate(updateDate.getTime());
+    }
+    return builder.build();
   }
 
-  private String toString(FieldDiffs currentChange) {
-    return currentChange != null ? currentChange.toString() : null;
+  private String diffsToString(@Nullable FieldDiffs diffs) {
+    return diffs != null ? diffs.toString() : null;
   }
 
 }
index 3ac79ee4187f3f4201aa2718d9094c86bbadd4a4..17a8c7e4c3253ebe3f9db041968060cc70c64086 100644 (file)
@@ -34,7 +34,7 @@ import org.sonar.api.utils.ZipUtils;
 import org.sonar.batch.bootstrap.DefaultAnalysisMode;
 import org.sonar.batch.bootstrap.ServerClient;
 import org.sonar.batch.index.ResourceCache;
-import org.sonar.batch.protocol.output.ReportHelper;
+import org.sonar.batch.protocol.output.BatchOutputWriter;
 
 import java.io.File;
 import java.io.IOException;
@@ -87,19 +87,19 @@ public class PublishReportJob implements BatchComponent {
     try {
       long startTime = System.currentTimeMillis();
       File reportDir = temp.newDir("batch-report");
-      ReportHelper reportHelper = ReportHelper.create(reportDir);
+      BatchOutputWriter writer = new BatchOutputWriter(reportDir);
       for (ReportPublisher publisher : publishers) {
-        publisher.export(reportHelper);
+        publisher.publish(writer);
       }
       long stopTime = System.currentTimeMillis();
-      LOG.debug("Analysis reports generated in " + (stopTime - startTime) + "ms");
+      LOG.info("Analysis reports generated in " + (stopTime - startTime) + "ms, dir size=" + FileUtils.byteCountToDisplaySize(FileUtils.sizeOfDirectory(reportDir)));
 
       startTime = System.currentTimeMillis();
       File reportZip = temp.newFile("batch-report", ".zip");
       ZipUtils.zipDir(reportDir, reportZip);
       FileUtils.deleteDirectory(reportDir);
       stopTime = System.currentTimeMillis();
-      LOG.debug("Analysis reports compressed in " + (stopTime - startTime) + "ms, zip size=" + FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(reportZip)));
+      LOG.info("Analysis reports compressed in " + (stopTime - startTime) + "ms, zip size=" + FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(reportZip)));
       return reportZip;
     } catch (IOException e) {
       throw new IllegalStateException("Unable to prepare batch report", e);
@@ -135,7 +135,7 @@ public class PublishReportJob implements BatchComponent {
       throw new IllegalStateException(String.format("Fail to execute request [code=%s, url=%s]: %s", responseCode, url, request.body()));
     }
     long stopTime = System.currentTimeMillis();
-    LOG.debug("Analysis reports sent to server in " + (stopTime - startTime) + "ms");
+    LOG.info("Analysis reports sent to server in " + (stopTime - startTime) + "ms");
   }
 
   @VisibleForTesting
index 32f93f64f106ae3a61edb36d58853483d7aa7251..6fe18f50889ac49580c4dd7bd1a0395ae060623a 100644 (file)
  */
 package org.sonar.batch.report;
 
-import org.sonar.batch.protocol.output.ReportHelper;
-
-import java.io.IOException;
+import org.sonar.batch.protocol.output.BatchOutputWriter;
 
+/**
+ * Adds a sub-part of data to output report
+ */
 public interface ReportPublisher {
 
-  void export(ReportHelper reportHelper) throws IOException;
+  void publish(BatchOutputWriter writer);
 
 }
index b9c0cebea7250b4a208756bf021e6222affe0775..87a72c6c0578dde9ab9c2b2bdd727f89a80805f5 100644 (file)
  */
 package org.sonar.batch.report;
 
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
-import org.skyscreamer.jsonassert.JSONAssert;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.bootstrap.ProjectReactor;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.resources.Directory;
 import org.sonar.api.resources.Java;
-import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Scopes;
+import org.sonar.api.utils.DateUtils;
 import org.sonar.batch.index.ResourceCache;
-import org.sonar.batch.protocol.output.ReportHelper;
+import org.sonar.batch.protocol.output.BatchOutputWriter;
+import org.sonar.batch.protocol.output.FileStructure;
 
-import java.io.File;
-import java.text.SimpleDateFormat;
+import static org.assertj.core.api.Assertions.assertThat;
 
 public class ComponentsPublisherTest {
 
   @Rule
   public TemporaryFolder temp = new TemporaryFolder();
 
-  @Test
-  public void testComponentPublisher() throws Exception {
-    ProjectReactor reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo"));
-    ResourceCache resourceCache = new ResourceCache();
-    ComponentsPublisher publisher = new ComponentsPublisher(reactor, resourceCache);
+  ProjectReactor reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo"));
+  ResourceCache resourceCache = new ResourceCache();
+  ComponentsPublisher publisher = new ComponentsPublisher(reactor, resourceCache);
 
-    Project root = new Project("foo").setName("Root project").setAnalysisDate(new SimpleDateFormat("dd/MM/yyyy").parse("12/12/2012"));
-    root.setId(1);
+  @Test
+  public void add_components_to_report() throws Exception {
+    // inputs
+    Project root = new Project("foo").setName("Root project")
+      .setAnalysisDate(DateUtils.parseDate(("2012-12-12")));
+    root.setId(1).setUuid("PROJECT_UUID");
     resourceCache.add(root, null).setSnapshot(new Snapshot().setId(11));
+
     Project module1 = new Project("module1").setName("Module1");
     module1.setParent(root);
-    module1.setId(2);
+    module1.setId(2).setUuid("MODULE_UUID");
     resourceCache.add(module1, root).setSnapshot(new Snapshot().setId(12));
-    Directory dir1 = Directory.create("src");
-    dir1.setEffectiveKey("foo:src");
-    dir1.setId(3);
-    resourceCache.add(dir1, module1).setSnapshot(new Snapshot().setId(13));
-    org.sonar.api.resources.File mainFile = org.sonar.api.resources.File.create("src/Foo.java", "Foo.java", Java.INSTANCE, false);
-    mainFile.setEffectiveKey("foo:src/Foo.java");
-    mainFile.setId(4);
-    resourceCache.add(mainFile, dir1).setSnapshot(new Snapshot().setId(14));
-    Directory dir2 = Directory.create("test");
-    dir2.setEffectiveKey("foo:test");
-    dir2.setId(5);
-    resourceCache.add(dir2, module1).setSnapshot(new Snapshot().setId(15));
-    org.sonar.api.resources.File testFile = org.sonar.api.resources.File.create("test/FooTest.java", "FooTest.java", Java.INSTANCE, true);
-    testFile.setEffectiveKey("foo:test/FooTest.java");
-    testFile.setId(6);
-    resourceCache.add(testFile, dir2).setSnapshot(new Snapshot().setId(16));
 
-    File exportDir = temp.newFolder();
-    ReportHelper helper = ReportHelper.create(exportDir);
-    publisher.export(helper);
+    Directory dir = Directory.create("src");
+    dir.setEffectiveKey("foo:src");
+    dir.setId(3).setUuid("DIR_UUID");
+    resourceCache.add(dir, module1).setSnapshot(new Snapshot().setId(13));
 
-    JSONAssert
-      .assertEquals(
-        IOUtils.toString(this.getClass().getResourceAsStream("ComponentsPublisherTest/expected.json"), "UTF-8"),
-        FileUtils.readFileToString(new File(exportDir, "components.json")), true);
-  }
+    org.sonar.api.resources.File file = org.sonar.api.resources.File.create("src/Foo.java", "Foo.java", Java.INSTANCE, false);
+    file.setEffectiveKey("foo:src/Foo.java");
+    file.setId(4).setUuid("FILE_UUID");
+    resourceCache.add(file, dir).setSnapshot(new Snapshot().setId(14));
 
-  @Test
-  public void testComponentPublisher_containing_file_without_language() throws Exception {
-    ProjectReactor reactor = new ProjectReactor(ProjectDefinition.create().setKey("ALL_PROJECT"));
-    ResourceCache resourceCache = new ResourceCache();
-    ComponentsPublisher publisher = new ComponentsPublisher(reactor, resourceCache);
-
-    View view = new View("ALL_PROJECT");
-    view.setId(1);
-    view.setAnalysisDate(new SimpleDateFormat("dd/MM/yyyy").parse("12/12/2012"));
-    resourceCache.add(view, null).setSnapshot(new Snapshot().setId(11));
-
-    org.sonar.api.resources.File mainFile = org.sonar.api.resources.File.create("ALL_PROJECTsample", "ALL_PROJECTsample", null, false);
-    mainFile.setEffectiveKey("ALL_PROJECTsample");
-    mainFile.setId(2);
-    resourceCache.add(mainFile, view).setSnapshot(new Snapshot().setId(12));
+    org.sonar.api.resources.File fileWithoutLang = org.sonar.api.resources.File.create("src/make", "make", null, false);
+    fileWithoutLang.setEffectiveKey("foo:src/make");
+    fileWithoutLang.setId(5).setUuid("FILE_WITHOUT_LANG_UUID");
+    resourceCache.add(fileWithoutLang, dir).setSnapshot(new Snapshot().setId(15));
 
-    File exportDir = temp.newFolder();
-    ReportHelper helper = ReportHelper.create(exportDir);
-    publisher.export(helper);
-
-    JSONAssert
-      .assertEquals(
-        IOUtils.toString(this.getClass().getResourceAsStream("ComponentsPublisherTest/testComponentPublisher_containing_file_without_language.json"), "UTF-8"),
-        FileUtils.readFileToString(new File(exportDir, "components.json")), true);
-  }
-
-  private static class View extends Project {
-
-    private View(String key) {
-      super(key);
-    }
-
-    @Override
-    public String getName() {
-      return "All Projects";
-    }
-
-    @Override
-    public String getLongName() {
-      return null;
-    }
-
-    @Override
-    public String getDescription() {
-      return null;
-    }
-
-    @Override
-    public Language getLanguage() {
-      return null;
-    }
-
-    @Override
-    public String getScope() {
-      return Scopes.PROJECT;
-    }
+    org.sonar.api.resources.File testFile = org.sonar.api.resources.File.create("test/FooTest.java", "FooTest.java", Java.INSTANCE, true);
+    testFile.setEffectiveKey("foo:test/FooTest.java");
+    testFile.setId(6).setUuid("TEST_FILE_UUID");
+    resourceCache.add(testFile, dir).setSnapshot(new Snapshot().setId(16));
 
-    @Override
-    public String getQualifier() {
-      return Qualifiers.VIEW;
-    }
+    BatchOutputWriter writer = new BatchOutputWriter(temp.newFolder());
+    publisher.publish(writer);
 
-    @Override
-    public Project getParent() {
-      return null;
-    }
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 1)).isTrue();
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 2)).isTrue();
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 3)).isTrue();
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 4)).isTrue();
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 5)).isTrue();
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 6)).isTrue();
 
-    @Override
-    public boolean matchFilePattern(String antPattern) {
-      return false;
-    }
+    // no such reference
+    assertThat(writer.hasComponentData(FileStructure.Domain.COMPONENT, 7)).isFalse();
   }
-
 }
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/report/ComponentsPublisherTest/expected.json b/sonar-batch/src/test/resources/org/sonar/batch/report/ComponentsPublisherTest/expected.json
deleted file mode 100644 (file)
index 09d60b6..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-{
-  "analysisDate": "2012-12-12T00:00:00+0100",
-  "root": {
-    "batchId": 1,
-    "id": 1,
-    "snapshotId": 11,
-    "name": "Root project",
-    "type": "PRJ",
-    "children": [
-      {
-        "batchId": 2,
-        "id": 2,
-        "snapshotId": 12,
-        "name": "Module1",
-        "type": "MOD",
-        "children": [
-          {
-            "batchId": 3,
-            "id": 3,
-            "snapshotId": 13,
-            "path": "src",
-            "type": "DIR",
-            "children": [
-              {
-                "batchId": 4,
-                "id": 4,
-                "snapshotId": 14,
-                "path": "src/Foo.java",
-                "type": "FIL",
-                "isTest": false,
-                "languageKey": "java",
-                "children": []
-              }
-            ]
-          },
-          {
-            "batchId": 5,
-            "id": 5,
-            "snapshotId": 15,
-            "path": "test",
-            "type": "DIR",
-            "children": [
-              {
-                "batchId": 6,
-                "id": 6,
-                "snapshotId": 16,
-                "path": "test/FooTest.java",
-                "type": "FIL",
-                "isTest": true,
-                "languageKey": "java",
-                "children": []
-              }
-            ]
-          }
-        ]
-      }
-    ]
-  }
-}
\ No newline at end of file
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/report/ComponentsPublisherTest/testComponentPublisher_containing_file_without_language.json b/sonar-batch/src/test/resources/org/sonar/batch/report/ComponentsPublisherTest/testComponentPublisher_containing_file_without_language.json
deleted file mode 100644 (file)
index 4c82576..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "analysisDate": "2012-12-12T00:00:00+0100",
-  "root": {
-    "batchId": 1,
-    "id": 1,
-    "snapshotId": 11,
-    "name": "All Projects",
-    "type": "VIEW",
-    "children": [
-      {
-        "batchId": 2,
-        "id": 2,
-        "snapshotId": 12,
-        "path": "ALL_PROJECTsample",
-        "type": "FIL",
-        "isTest": false,
-        "children": []
-      }
-    ]
-  }
-}
index f60e7fb8f53d80ff892eb54cde31438050e8f887..5ba09482ff4f82593823ef2d5d5363ea82394139 100644 (file)
@@ -21,7 +21,9 @@ package org.sonar.api.utils;
 
 import com.google.common.collect.Iterators;
 import org.apache.commons.io.FileUtils;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 
 import java.io.File;
 import java.io.IOException;
@@ -34,24 +36,33 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 public class ZipUtilsTest {
 
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
   @Test
   public void shouldZipDirectory() throws IOException {
     File foo = FileUtils.toFile(getClass().getResource("/org/sonar/api/utils/ZipUtilsTest/shouldZipDirectory/foo.txt"));
     File dir = foo.getParentFile();
-    File zip = new File("target/tmp/shouldZipDirectory.zip");
+    File zip = temp.newFile();
 
     ZipUtils.zipDir(dir, zip);
 
-    assertThat(zip).exists();
+    assertThat(zip).exists().isFile();
     assertThat(zip.length()).isGreaterThan(1L);
     Iterator<? extends ZipEntry> zipEntries = Iterators.forEnumeration(new ZipFile(zip).entries());
     assertThat(zipEntries).hasSize(4);
+
+    File unzipDir = temp.newFolder();
+    ZipUtils.unzip(zip, unzipDir);
+    assertThat(new File(unzipDir, "bar.txt")).exists().isFile();
+    assertThat(new File(unzipDir, "foo.txt")).exists().isFile();
+    assertThat(new File(unzipDir, "dir1/hello.properties")).exists().isFile();
   }
 
   @Test
   public void shouldUnzipFile() throws IOException {
     File zip = FileUtils.toFile(getClass().getResource("/org/sonar/api/utils/ZipUtilsTest/shouldUnzipFile.zip"));
-    File toDir = new File("target/tmp/shouldUnzipFile/");
+    File toDir = temp.newFolder();
     ZipUtils.unzip(zip, toDir);
     assertThat(toDir.list()).hasSize(3);
   }
@@ -59,7 +70,7 @@ public class ZipUtilsTest {
   @Test
   public void should_unzip_stream_file() throws Exception {
     InputStream zip = getClass().getResource("/org/sonar/api/utils/ZipUtilsTest/shouldUnzipFile.zip").openStream();
-    File toDir = new File("target/tmp/shouldUnzipStreamFile/");
+    File toDir = temp.newFolder();
     ZipUtils.unzip(zip, toDir);
     assertThat(toDir.list()).hasSize(3);
   }